.. _languageRulesDoc: ============== Language Rules ============== * `Port Types`_ * `Rate Propagation`_ * `Token Propagation`_ ---- Port Types ========== :: module Add { input: Inputs output: Output propertyName: 'reset' propertyBlock: trigger Reset {} internalBlock: [ hybrid Inputs [2] { type: [ 'Stream Real', 'Stream Integer', 'Constant Real', 'Constant Integer' ] default : [ 0.0, 0 ] rate: streamRate domain: streamDomain reset: Reset }, hybrid Output { type: [ 'Stream Real', 'Stream Integer' ] default : [ 0.0, 0 ] rate: streamRate domain: streamDomain reset: Reset } ] streams: Inputs[1] + Inputs[2] >> Output; } :: signal Output { default: 0 rate: none } # Add operates in Integer (based on input) # Output is 2 [ 1 , 1 ] >> Add ( reset: none ) >> Output; # Add operates in Real (based on input) # Output is 2 (truncation at Output's input) [ 1.0 , 1 ] >> Add ( reset: none ) >> Output; # Add operates in Real (based on input) # Output is 2 (truncation at Output's input) [ 1.0 , 1.0 ] >> Add ( reset: none ) >> Output; :: signal Output { default: 0.0 rate: none } # Add operates in Integer (based on input) # Output is 2.0 (Integer to Real conversion at Output's input port) [ 1 , 1 ] >> Add ( reset: none ) >> Output; # Add operates in Real (based on input) # Output is 2.0 [ 1.0 , 1 ] >> Add ( reset: none ) >> Output; # Add operates in Real (based on input) # Output is 2.0 [ 1.0 , 1.0 ] >> Add ( reset: none ) >> Output; ---- :: module Level { input: Inputs output: Output propertyName: [ 'gainType', 'gain', 'offset', 'bypass' ] propertyDirection: in propertyBlock: [ constant GainType { value: 'Linear' }, hybrid Gain { type: [ 'Stream Real', 'Stream Integer', 'Constant Real', 'Constant Integer' ] default : [ 1.0, 1 ] rate: none domain: inputDomain # Perhaps another word? reset: none }, hybrid Offset { type: [ 'Stream Real', 'Stream Integer', 'Constant Real', 'Constant Integer' ] default : [ 0.0, 0 ] rate: streamRate domain: streamDomain reset: none }, switch Bypass { default: off reset: none} ] internalBlock: [ hybrid Input { type: [ 'Stream Real', 'Stream Integer', 'Constant Real', 'Constant Integer' ] default : [ 0.0, 0 ] rate: streamRate domain: streamDomain reset: Reset }, hybrid Output { type: [ 'Stream Real', 'Stream Integer' ] default : [ 0.0, 0 ] rate: streamRate domain: streamDomain reset: Reset }, hybrid NormalizedGain { type: [ 'Stream Real', 'Stream Integer' ] default : [ 1.0, 1 ] rate: streamRate domain: streamDomain reset: Reset }, dictionary GainTypeDictionary { key: [ 'Linear', 'Decibel' ] value: [ 1, 2 ] } ] streams: [ [ Gain , 10 >> Power ( exponent: Gain / 20 ) ] >> GetPort ( index: GetDictionaryValue ( dictionaryName: GainTypeDictionary key: GainType ) >> NormalizedGain; Input * NormalizedGain + Offset >> Result; Bypass >> Select ( whenOn: Input whenOff: Result ) >> Output; ] } :: signal Input { default: 1 rate: none } signal Output { default: 1 rate: none } # Input is Integer # Level operates in Integer # Output is 2 Input >> Level ( gain: 2 ) >> Output; # Input is Integer # Level operates in Real (based on property) # Output is 2 (truncation at Output's input) Input >> Level ( gain: 2.0 ) >> Output; :: signal Input { default: 1.0 rate: none } signal Output { default: 1 rate: none } # Input is Real # Level operates in Real (based on input) # Output is 2 (truncation at Output's input) Input >> Level ( gain: 2 ) >> Output; # Input is Real # Level operates in Real (based on input and property) # Output is 2 (Integer to Real conversion at Output's input port) Input >> Level ( gain: 2.0 ) >> Output; :: signal Input { default: 1 rate: none } signal Output { default: 1.0 rate: none } # Input is Integer # Level operates in Integer (based on input and property) # Output is 2.0 (Output's input) Input >> Level ( gain: 2 ) >> Output; # Input is Integer # Level operates in Real (based on property) # Output is 2.0 Input >> Level ( gain: 2.0 ) >> Output; ---- Rate Propagation ================ Rates in a stream expression propagate from right to left. A block samples its input port at a fixed rate and generates tokens at its output port. In the following example A generates tokens at 1 Hz. B samples its input port and 2 Hz and generates tokens at the same rate. :: signal A { default: 0 rate: 1 domain: D } signal B { default: 0 rate: 2 domain: D } A + 1 >> A; A >> B; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | 2 | 3 | 4 | +--------+---+---+---+---+---+---+---+---+ | B | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: 1 domain: D } signal B { default: 0 rate: 2 domain: D } A >> B; A + 1 >> A; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | 2 | 3 | 4 | +--------+---+---+---+---+---+---+---+---+ | B | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: 2 domain: D } signal B { default: 0 rate: 1 domain: D } A + 1 >> A; A >> B; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +--------+---+---+---+---+---+---+---+---+ | B | 1 | 3 | 5 | 7 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: 2 domain: D } signal B { default: 0 rate: 1 domain: D } A >> B; A + 1 >> A; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +--------+---+---+---+---+---+---+---+---+ | B | 0 | 2 | 4 | 6 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: none domain: D } signal B { default: 0 rate: 2 domain: D } A + 1 >> A; A >> B; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | +--------+---+---+---+---+---+---+---+---+ | B | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: none domain: D } signal B { default: 0 rate: 2 domain: D } A >> B; A + 1 >> A; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | +--------+---+---+---+---+---+---+---+---+ | B | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: 2 domain: D } signal B { default: 0 rate: 1 domain: D } RandomNumber ( minimum: 1 maximum: 3 ) >> A >> B; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | 3 | 3 | 2 | 1 | 1 | 2 | 3 | +--------+---+---+---+---+---+---+---+---+ | B | 1 | 3 | 1 | 2 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: 2 domain: D } signal B { default: 0 rate: none domain: D } RandomNumber ( minimum: 1 maximum: 3 ) >> A >> B; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | 3 | 3 | 2 | 1 | 1 | 2 | 3 | +--------+---+---+---+---+---+---+---+---+ | B | 1 | 3 | 3 | 2 | 1 | 1 | 2 | 3 | +--------+---+---+---+---+---+---+---+---+ ---- :: signal A { default: 0 rate: 2 domain: D } signal B { default: 0 rate: none domain: D } RandomNumber ( minimum: 1 maximum: 3 ) >> A >> OnChange () >> B; +--------+---+---+---+---+---+---+---+---+ | Clock | x | x | x | x | x | x | x | x | +--------+---+---+---+---+---+---+---+---+ | A | 1 | 3 | 3 | 2 | 1 | 1 | 2 | 3 | +--------+---+---+---+---+---+---+---+---+ | B | 1 | 3 | 2 | 1 | 2 | 3 | +--------+---+---+---+---+---+---+---+---+ ---- Token Propagation ================= Tokens propagate from left to right. * Rates are constant * Rate can be ``streamRate`` or ``none``