Class: HDLRuby::Low::Code

Inherits:
Base::Code
  • Object
show all
Includes:
Hparent, Low2Symbol
Defined in:
lib/HDLRuby/hruby_db.rb,
lib/HDLRuby/hruby_low.rb,
lib/HDLRuby/hruby_low2c.rb,
lib/HDLRuby/hruby_low2hdr.rb,
lib/HDLRuby/hruby_low2sym.rb,
lib/HDLRuby/hruby_low2vhd.rb,
lib/HDLRuby/hruby_low2high.rb,
lib/HDLRuby/hruby_low_mutable.rb,
lib/HDLRuby/hruby_low_skeleton.rb,
lib/HDLRuby/backend/hruby_c_allocator.rb,
lib/HDLRuby/hdrlib.rb,
lib/HDLRuby/hdrcc.rb

Overview

Extend the Code class with generation of file for the content.

Direct Known Subclasses

High::Code

Constant Summary

Constants included from Low2Symbol

Low2Symbol::Low2SymbolPrefix, Low2Symbol::Low2SymbolTable, Low2Symbol::Symbol2LowTable

Instance Attribute Summary

Attributes included from Hparent

#parent

Instance Method Summary collapse

Methods included from Low2Symbol

#to_sym

Methods included from Hparent

#hierarchy, #no_parent!, #scope

Constructor Details

#initializeCode

Creates a new chunk of code.



2946
2947
2948
2949
2950
2951
# File 'lib/HDLRuby/hruby_low.rb', line 2946

def initialize
    # Initialize the set of events.
    @events = []
    # Initialize the content.
    @chunks = HashName.new
end

Instance Method Details

#add_chunk(chunk) ⇒ Object

Adds a +chunk+ to the sensitivity list.



2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
# File 'lib/HDLRuby/hruby_low.rb', line 2957

def add_chunk(chunk)
    # Check and add the chunk.
    unless chunk.is_a?(Chunk)
        raise AnyError,
              "Invalid class for a code chunk: #{chunk.class}"
    end
    # if @chunks.include?(chunk) then
    #     raise AnyError, "Code chunk #{chunk.name} already present."
    # end
    # Set its parent.
    chunk.parent = self
    # And add it
    @chunks.add(chunk)
end

#add_event(event) ⇒ Object

Adds an +event+ to the sensitivity list.



2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
# File 'lib/HDLRuby/hruby_low.rb', line 2983

def add_event(event)
    unless event.is_a?(Event)
        raise AnyError, "Invalid class for a event: #{event.class}"
    end
    # Set the event's parent.
    event.parent = self
    # And add the event.
    @events << event
    event
end

#c_code_allocate(allocator) ⇒ Object

Allocates signals within C code using +allocator+.



68
69
70
71
72
73
# File 'lib/HDLRuby/backend/hruby_c_allocator.rb', line 68

def c_code_allocate(allocator)
    # Apply the allocator on each C chunk.
    self.each_chunk do |chunk|
        chunk.c_code_allocate!(allocator) if chunk.name == :c
    end
end

#each_chunk(&ruby_block) ⇒ Object

Iterates over the code chunks.

Returns an enumerator if no ruby block is given.



2975
2976
2977
2978
2979
2980
# File 'lib/HDLRuby/hruby_low.rb', line 2975

def each_chunk(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_chunk) unless ruby_block
    # A ruby block? Apply it on each chunk.
    @chunks.each(&ruby_block)
end

#each_deep(&ruby_block) ⇒ Object

Iterates over each object deeply.

Returns an enumerator if no ruby block is given.



3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
# File 'lib/HDLRuby/hruby_low.rb', line 3020

def each_deep(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_deep) unless ruby_block
    # A ruby block? First apply it to current.
    ruby_block.call(self)
    # Then apply on each chunk.
    self.each_chunk do |chunk|
        chunk.each_deep(&ruby_block)
    end
    # Then apply on each event.
    self.each_event do |event|
        event.each_deep(&ruby_block)
    end
end

#each_event(&ruby_block) ⇒ Object

Iterates over the events of the sensitivity list.

Returns an enumerator if no ruby block is given.



2997
2998
2999
3000
3001
3002
# File 'lib/HDLRuby/hruby_low.rb', line 2997

def each_event(&ruby_block)
    # No ruby block? Return an enumerator.
    return to_enum(:each_event) unless ruby_block
    # A ruby block? Apply it on each event.
    @events.each(&ruby_block)
end

#eql?(obj) ⇒ Boolean

Comparison for hash: structural comparison.

Returns:

  • (Boolean)


3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
# File 'lib/HDLRuby/hruby_low.rb', line 3036

def eql?(obj)
    return false unless obj.is_a?(Code)
    idx = 0
    obj.each_event do |event|
        return false unless @events[idx].eql?(event)
        idx += 1
    end
    idx = 0
    obj.each_chunk do |chunk|
        return false unless @chunks[idx].eql?(chunk)
        idx += 1
    end
    return true
end

#has_event?Boolean

Tells if there is any event.

Returns:

  • (Boolean)


3005
3006
3007
# File 'lib/HDLRuby/hruby_low.rb', line 3005

def has_event?
    return !@events.empty?
end

#hashObject

Hash function.



3052
3053
3054
# File 'lib/HDLRuby/hruby_low.rb', line 3052

def hash
    return [@events,@chunk].hash
end

#on_edge?Boolean

Tells if there is a positive or negative edge event.

Returns:

  • (Boolean)


3010
3011
3012
3013
3014
3015
# File 'lib/HDLRuby/hruby_low.rb', line 3010

def on_edge?
    @events.each do |event|
        return true if event.on_edge?
    end
    return false
end

#set_content!(content) ⇒ Object

Sets the content.



1296
1297
1298
1299
1300
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1296

def set_content!(content)
    @content = content
    # Freeze it to avoid dynamic tempering of the hardware.
    content.freeze
end

#set_type!(type) ⇒ Object

Sets the type.



1290
1291
1292
1293
# File 'lib/HDLRuby/hruby_low_mutable.rb', line 1290

def set_type!(type)
    # Check and set type.
    @type = type.to_sym
end

#to_c(res, level = 0) ⇒ Object

Generates the C text of the equivalent HDLRuby code. +level+ is the hierachical level of the object. def to_c(level = 0)



1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
# File 'lib/HDLRuby/hruby_low2c.rb', line 1206

def to_c(res,level = 0)
    # puts "For behavior: #{self}"
    # The resulting string.
    # res = ""

    # Declare the global variable holding the behavior.
    res << "Code " << Low2C.obj_name(self) << ";\n\n"

    # Generate the code of the behavior.
    
    # The header of the behavior.
    res << " " * level*3
    res << "Code " << Low2C.make_name(self) << "() {\n"
    res << " " * (level+1)*3

    # Allocate the code.
    res << "Code code = malloc(sizeof(CodeS));\n"
    res << " " * (level+1)*3
    res << "code->kind = CODE;\n";

    # Sets the global variable of the code.
    res << "\n"
    res << " " * (level+1)*3
    res << Low2C.obj_name(self) << " = code;\n"

    # Set the owner if any.
    if self.parent then
        res << " " * (level+1)*3
        res << "code->owner = (Object)"
        res << Low2C.obj_name(self.parent) << ";\n"
    else
        res << "code->owner = NULL;\n"
    end

    # Set the code as enabled (for now, may change in a near future). */
    res << " " * (level+1)*3
    res << "code->enabled = 1;\n"

    # Set the code as inactive. */
    res << " " * (level+1)*3
    res << "code->activated = 0;\n"

    # Add the events and register the code as activable
    # on them.
    res << " " * (level+1)*3
    res << "code->num_events = #{self.each_event.to_a.size};\n"
    res << " " * (level+1)*3
    res << "code->events = calloc(sizeof(Event)," +
           "code->num_events);\n"
    # Process the events.
    events = self.each_event.to_a
    events.each_with_index do |event,i|
        # puts "for event=#{event}"
        # Add the event.
        res << " " * (level+1)*3
        # res << "code->events[#{i}] = #{event.to_c};\n"
        res << "code->events[#{i}] = "
        event.to_c(res)
        res << ";\n"
        
        # Register the behavior as activable on this event.
        # Select the active field.
        field = "any"
        field = "pos" if event.type == :posedge
        field = "neg" if event.type == :negedge
        # Get the target signal access
        # sigad = event.ref.resolve.to_c_signal
        sigad = ""
        event.ref.resolve.to_c_signal(sigad)
        # Add the code to the relevant field.
        res << " " * (level+1)*3
        res << "#{sigad}->num_#{field} += 1;\n"
        res << " " * (level+1)*3
        res << "#{sigad}->#{field} = realloc(#{sigad}->#{field}," +
               "#{sigad}->num_#{field}*sizeof(Object));\n"
        res << "#{sigad}->#{field}[#{sigad}->num_#{field}-1] = " +
               "(Object)code;\n"
    end

    # Adds the function to execute.
    function = self.each_chunk.find { |chunk| chunk.name == :sim }
    res << " " * (level+1)*3
    # res << "code->function = &#{function.to_c};\n"
    res << "code->function = &"
    function.to_c(res)
    res << ";\n"

    # Generate the Returns of the result.
    res << "\n"
    res << " " * (level+1)*3
    res << "return code;\n"

    # Close the behavior makeing.
    res << " " * level*3
    res << "}\n\n"
    return res
end

#to_ch(res) ⇒ Object

Generates the content of the h file. def to_ch



1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
# File 'lib/HDLRuby/hruby_low2c.rb', line 1306

def to_ch(res)
    # res = ""
    # Declare the global variable holding the signal.
    res << "extern Behavior " << Low2C.obj_name(self) << ";\n\n"

    # Generate the access to the function making the behavior.
    res << "extern Behavior " << Low2C.make_name(self) << "();\n\n"

    # Generate the accesses to the block of the behavior.
    # res << self.block.to_ch
    self.block.to_ch(res)

    return res;
end

#to_file(path = "") ⇒ Object

Creates a file in +path+ containing the content of the code.



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/HDLRuby/hdrlib.rb', line 233

def to_file(path = "")
    self.each_chunk do |chunk|
        # Process the lumps of the chunk.
        # NOTE: for now use the C code generation of Low2C
        content = chunk.to_c
        # Dump to a file.
        if chunk.name != :sim then 
            # The chunk is to be dumbed to a file.
            # show? "Outputing chunk:#{HDLRuby::Low::Low2C.obj_name(chunk)}"
            outfile = File.open(path + "/" +
                               HDLRuby::Low::Low2C.obj_name(chunk) + "." +
                               chunk.name.to_s,"w")
            outfile << content
            outfile.close
        end
    end
end

#to_hdr(level = 0) ⇒ Object

Generates the text of the equivalent hdr text. +level+ is the hierachical level of the object.



526
527
528
# File 'lib/HDLRuby/hruby_low2hdr.rb', line 526

def to_hdr(level = 0)
    return self.content.to_s
end

#to_highObject

Creates a new high code.



218
219
220
221
222
223
224
225
# File 'lib/HDLRuby/hruby_low2high.rb', line 218

def to_high
    # Create the new code.
    res = HDLRuby::High::Code.new
    # Add the events.
    self.each_event { |ev| res.add_event(ev.to_high) }
    # Add the code chunks.
    self.each_chunk { |ch| res.add_chunk(ch.to_high) }
end

#to_vhdl(level = 0) ⇒ Object

Generates the text of the equivalent HDLRuby::High code. +level+ is the hierachical level of the object.



1129
1130
1131
# File 'lib/HDLRuby/hruby_low2vhd.rb', line 1129

def to_vhdl(level = 0)
    raise "Code constructs cannot be converted into VHDL."
end