Write flop tests using generator
This commit is contained in:
@@ -1,333 +1,334 @@
|
|||||||
//~ package barstools.tapeout.transforms.macros
|
package barstools.macros
|
||||||
|
|
||||||
//~ import java.io.File
|
// Use this trait for tests that invoke the memory compiler without lib.
|
||||||
|
trait HasNoLibTestGenerator extends HasSimpleTestGenerator {
|
||||||
|
this: MacroCompilerSpec with HasSRAMGenerator =>
|
||||||
|
|
||||||
//~ class Synflops2048x16_mrw extends MacroCompilerSpec {
|
// If there isn't a lib, then the "lib" will become a FIRRTL "mem", which
|
||||||
//~ val mem = new File(macroDir, "mem-2048x16-mrw.json")
|
// in turn becomes synthesized flops.
|
||||||
//~ val v = new File(testDir, "syn_flops_2048x16_mrw.v")
|
// Therefore, make "lib" width/depth equal to the mem.
|
||||||
//~ val output =
|
override lazy val libDepth = memDepth
|
||||||
//~ """
|
override lazy val libWidth = memWidth
|
||||||
//~ circuit name_of_sram_module :
|
// Do the same for port names.
|
||||||
//~ module name_of_sram_module :
|
override lazy val libPortPrefix = memPortPrefix
|
||||||
//~ input clock : Clock
|
|
||||||
//~ input RW0A : UInt<11>
|
|
||||||
//~ input RW0I : UInt<16>
|
|
||||||
//~ output RW0O : UInt<16>
|
|
||||||
//~ input RW0E : UInt<1>
|
|
||||||
//~ input RW0W : UInt<1>
|
|
||||||
//~ input RW0M : UInt<2>
|
|
||||||
|
|
||||||
//~ mem ram :
|
// If there is no lib, don't generate a body.
|
||||||
//~ data-type => UInt<8>[2]
|
override def generateBody = ""
|
||||||
//~ depth => 2048
|
}
|
||||||
//~ read-latency => 0
|
|
||||||
//~ write-latency => 1
|
|
||||||
//~ reader => R_0
|
|
||||||
//~ writer => W_0
|
|
||||||
//~ read-under-write => undefined
|
|
||||||
//~ reg R_0_addr_reg : UInt<11>, clock with :
|
|
||||||
//~ reset => (UInt<1>("h0"), R_0_addr_reg)
|
|
||||||
//~ ram.R_0.clk <= clock
|
|
||||||
//~ ram.R_0.addr <= R_0_addr_reg
|
|
||||||
//~ ram.R_0.en <= RW0E
|
|
||||||
//~ RW0O <= cat(ram.R_0.data[1], ram.R_0.data[0])
|
|
||||||
//~ R_0_addr_reg <= mux(RW0E, RW0A, R_0_addr_reg)
|
|
||||||
//~ ram.W_0.clk <= clock
|
|
||||||
//~ ram.W_0.addr <= RW0A
|
|
||||||
//~ ram.W_0.en <= and(RW0E, RW0W)
|
|
||||||
//~ ram.W_0.data[0] <= bits(RW0I, 7, 0)
|
|
||||||
//~ ram.W_0.data[1] <= bits(RW0I, 15, 8)
|
|
||||||
//~ ram.W_0.mask[0] <= bits(RW0M, 0, 0)
|
|
||||||
//~ ram.W_0.mask[1] <= bits(RW0M, 1, 1)
|
|
||||||
//~ """
|
|
||||||
//~ compile(mem, None, v, true)
|
|
||||||
//~ execute(Some(mem), None, true, output)
|
|
||||||
//~ }
|
|
||||||
|
|
||||||
//~ class Synflops2048x8_r_mw extends MacroCompilerSpec {
|
// Test flop synthesis of the memory compiler.
|
||||||
//~ val mem = new File(macroDir, "mem-2048x8-r-mw.json")
|
|
||||||
//~ val v = new File(testDir, "syn_flops_2048x8_r_mw.v")
|
|
||||||
//~ val output =
|
|
||||||
//~ """
|
|
||||||
//~ circuit name_of_sram_module :
|
|
||||||
//~ module name_of_sram_module :
|
|
||||||
//~ input clock : Clock
|
|
||||||
//~ input W0A : UInt<11>
|
|
||||||
//~ input W0I : UInt<8>
|
|
||||||
//~ input W0E : UInt<1>
|
|
||||||
//~ input W0M : UInt<1>
|
|
||||||
//~ input clock : Clock
|
|
||||||
//~ input R0A : UInt<11>
|
|
||||||
//~ output R0O : UInt<8>
|
|
||||||
|
|
||||||
//~ mem ram :
|
trait HasSynFlopsTestGenerator extends HasSimpleTestGenerator {
|
||||||
//~ data-type => UInt<8>[1]
|
this: MacroCompilerSpec with HasSRAMGenerator =>
|
||||||
//~ depth => 2048
|
def generateFlops: String = {
|
||||||
//~ read-latency => 0
|
s"""
|
||||||
//~ write-latency => 1
|
mem ram :
|
||||||
//~ reader => R_0
|
data-type => UInt<${libWidth}>
|
||||||
//~ writer => W_0
|
depth => ${libDepth}
|
||||||
//~ read-under-write => undefined
|
read-latency => 1
|
||||||
//~ reg R_0_addr_reg : UInt<11>, clock with :
|
write-latency => 1
|
||||||
//~ reset => (UInt<1>("h0"), R_0_addr_reg)
|
readwriter => RW_0
|
||||||
//~ ram.R_0.clk <= clock
|
read-under-write => undefined
|
||||||
//~ ram.R_0.addr <= R_0_addr_reg
|
ram.RW_0.clk <= ${libPortPrefix}_clk
|
||||||
//~ ram.R_0.en <= UInt<1>("h1")
|
ram.RW_0.addr <= ${libPortPrefix}_addr
|
||||||
//~ R0O <= ram.R_0.data[0]
|
ram.RW_0.en <= UInt<1>("h1")
|
||||||
//~ R_0_addr_reg <= mux(UInt<1>("h1"), R0A, R_0_addr_reg)
|
ram.RW_0.wmode <= ${libPortPrefix}_write_en
|
||||||
//~ ram.W_0.clk <= clock
|
${libPortPrefix}_dout <= ram.RW_0.rdata
|
||||||
//~ ram.W_0.addr <= W0A
|
ram.RW_0.wdata <= ${libPortPrefix}_din
|
||||||
//~ ram.W_0.en <= W0E
|
ram.RW_0.wmask <= UInt<1>("h1")
|
||||||
//~ ram.W_0.data[0] <= bits(W0I, 7, 0)
|
"""
|
||||||
//~ ram.W_0.mask[0] <= bits(W0M, 0, 0)
|
}
|
||||||
//~ """
|
|
||||||
//~ compile(mem, None, v, true)
|
|
||||||
//~ execute(Some(mem), None, true, output)
|
|
||||||
//~ }
|
|
||||||
|
|
||||||
//~ class Synflops2048x10_rw extends MacroCompilerSpec {
|
// If there is no lib, put the flops definition into the body.
|
||||||
//~ val mem = new File(macroDir, "lib-2048x10-rw.json")
|
abstract override def generateBody = {
|
||||||
//~ val v = new File(testDir, "syn_flops_2048x10_rw.v")
|
if (this.isInstanceOf[HasNoLibTestGenerator]) generateFlops else super.generateBody
|
||||||
//~ val output =
|
}
|
||||||
//~ """
|
|
||||||
//~ circuit vendor_sram :
|
|
||||||
//~ module vendor_sram :
|
|
||||||
//~ input clock : Clock
|
|
||||||
//~ input RW0A : UInt<11>
|
|
||||||
//~ input RW0I : UInt<10>
|
|
||||||
//~ output RW0O : UInt<10>
|
|
||||||
//~ input RW0E : UInt<1>
|
|
||||||
//~ input RW0W : UInt<1>
|
|
||||||
|
|
||||||
//~ mem ram :
|
// If there is no lib, don't generate a footer, since the flops definition
|
||||||
//~ data-type => UInt<10>
|
// will be in the body.
|
||||||
//~ depth => 2048
|
override def generateFooter = {
|
||||||
//~ read-latency => 0
|
if (this.isInstanceOf[HasNoLibTestGenerator]) "" else
|
||||||
//~ write-latency => 1
|
s"""
|
||||||
//~ reader => R_0
|
module ${lib_name} :
|
||||||
//~ writer => W_0
|
${generateFooterPorts}
|
||||||
//~ read-under-write => undefined
|
|
||||||
//~ reg R_0_addr_reg : UInt<11>, clock with :
|
|
||||||
//~ reset => (UInt<1>("h0"), R_0_addr_reg)
|
|
||||||
//~ ram.R_0.clk <= clock
|
|
||||||
//~ ram.R_0.addr <= R_0_addr_reg
|
|
||||||
//~ ram.R_0.en <= RW0E
|
|
||||||
//~ RW0O <= ram.R_0.data
|
|
||||||
//~ R_0_addr_reg <= mux(RW0E, RW0A, R_0_addr_reg)
|
|
||||||
//~ ram.W_0.clk <= clock
|
|
||||||
//~ ram.W_0.addr <= RW0A
|
|
||||||
//~ ram.W_0.en <= and(RW0E, RW0W)
|
|
||||||
//~ ram.W_0.data <= RW0I
|
|
||||||
//~ ram.W_0.mask <= UInt<1>("h1")
|
|
||||||
//~ """
|
|
||||||
//~ compile(mem, None, v, true)
|
|
||||||
//~ execute(Some(mem), None, true, output)
|
|
||||||
//~ }
|
|
||||||
|
|
||||||
//~ class Synflops2048x8_mrw_re extends MacroCompilerSpec {
|
${generateFlops}
|
||||||
//~ val mem = new File(macroDir, "lib-2048x8-mrw-re.json")
|
"""
|
||||||
//~ val v = new File(testDir, "syn_flops_2048x8_mrw_re.v")
|
}
|
||||||
//~ val output =
|
|
||||||
//~ """
|
|
||||||
//~ circuit vendor_sram :
|
|
||||||
//~ module vendor_sram :
|
|
||||||
//~ input clock : Clock
|
|
||||||
//~ input RW0A : UInt<11>
|
|
||||||
//~ input RW0I : UInt<8>
|
|
||||||
//~ output RW0O : UInt<8>
|
|
||||||
//~ input RW0E : UInt<1>
|
|
||||||
//~ input RW0R : UInt<1>
|
|
||||||
//~ input RW0W : UInt<1>
|
|
||||||
//~ input RW0M : UInt<1>
|
|
||||||
|
|
||||||
//~ mem ram :
|
}
|
||||||
//~ data-type => UInt<8>[1]
|
|
||||||
//~ depth => 2048
|
|
||||||
//~ read-latency => 0
|
|
||||||
//~ write-latency => 1
|
|
||||||
//~ reader => R_0
|
|
||||||
//~ writer => W_0
|
|
||||||
//~ read-under-write => undefined
|
|
||||||
//~ reg R_0_addr_reg : UInt<11>, clock with :
|
|
||||||
//~ reset => (UInt<1>("h0"), R_0_addr_reg)
|
|
||||||
//~ ram.R_0.clk <= clock
|
|
||||||
//~ ram.R_0.addr <= R_0_addr_reg
|
|
||||||
//~ ram.R_0.en <= and(RW0E, not(RW0R))
|
|
||||||
//~ RW0O <= ram.R_0.data[0]
|
|
||||||
//~ R_0_addr_reg <= mux(and(RW0E, not(RW0R)), RW0A, R_0_addr_reg)
|
|
||||||
//~ ram.W_0.clk <= clock
|
|
||||||
//~ ram.W_0.addr <= RW0A
|
|
||||||
//~ ram.W_0.en <= and(RW0E, RW0W)
|
|
||||||
//~ ram.W_0.data[0] <= bits(RW0I, 7, 0)
|
|
||||||
//~ ram.W_0.mask[0] <= bits(RW0M, 0, 0)
|
|
||||||
//~ """
|
|
||||||
//~ compile(mem, None, v, true)
|
|
||||||
//~ execute(Some(mem), None, true, output)
|
|
||||||
//~ }
|
|
||||||
|
|
||||||
//~ class Synflops2048x16_n28 extends MacroCompilerSpec {
|
class Synflops2048x8_noLib extends MacroCompilerSpec with HasSRAMGenerator with HasNoLibTestGenerator with HasSynFlopsTestGenerator {
|
||||||
//~ val mem = new File(macroDir, "lib-2048x16-n28.json")
|
override lazy val memDepth = 2048
|
||||||
//~ val v = new File(testDir, "syn_flops_2048x16_n28.v")
|
override lazy val memWidth = 8
|
||||||
//~ val output =
|
|
||||||
//~ """
|
|
||||||
//~ circuit vendor_sram_4 :
|
|
||||||
//~ module vendor_sram_16 :
|
|
||||||
//~ input clock : Clock
|
|
||||||
//~ input RW0A : UInt<11>
|
|
||||||
//~ input RW0I : UInt<16>
|
|
||||||
//~ output RW0O : UInt<16>
|
|
||||||
//~ input RW0E : UInt<1>
|
|
||||||
//~ input RW0W : UInt<1>
|
|
||||||
//~ input RW0M : UInt<16>
|
|
||||||
|
|
||||||
//~ mem ram :
|
compileExecuteAndTest(mem, None, v, output, true)
|
||||||
//~ data-type => UInt<1>[16]
|
}
|
||||||
//~ depth => 2048
|
|
||||||
//~ read-latency => 0
|
|
||||||
//~ write-latency => 1
|
|
||||||
//~ reader => R_0
|
|
||||||
//~ writer => W_0
|
|
||||||
//~ read-under-write => undefined
|
|
||||||
//~ reg R_0_addr_reg : UInt<11>, clock with :
|
|
||||||
//~ reset => (UInt<1>("h0"), R_0_addr_reg)
|
|
||||||
//~ ram.R_0.clk <= clock
|
|
||||||
//~ ram.R_0.addr <= R_0_addr_reg
|
|
||||||
//~ ram.R_0.en <= RW0E
|
|
||||||
//~ RW0O <= cat(ram.R_0.data[15], cat(ram.R_0.data[14], cat(ram.R_0.data[13], cat(ram.R_0.data[12], cat(ram.R_0.data[11], cat(ram.R_0.data[10], cat(ram.R_0.data[9], cat(ram.R_0.data[8], cat(ram.R_0.data[7], cat(ram.R_0.data[6], cat(ram.R_0.data[5], cat(ram.R_0.data[4], cat(ram.R_0.data[3], cat(ram.R_0.data[2], cat(ram.R_0.data[1], ram.R_0.data[0])))))))))))))))
|
|
||||||
//~ R_0_addr_reg <= mux(RW0E, RW0A, R_0_addr_reg)
|
|
||||||
//~ ram.W_0.clk <= clock
|
|
||||||
//~ ram.W_0.addr <= RW0A
|
|
||||||
//~ ram.W_0.en <= and(RW0E, RW0W)
|
|
||||||
//~ ram.W_0.data[0] <= bits(RW0I, 0, 0)
|
|
||||||
//~ ram.W_0.data[1] <= bits(RW0I, 1, 1)
|
|
||||||
//~ ram.W_0.data[2] <= bits(RW0I, 2, 2)
|
|
||||||
//~ ram.W_0.data[3] <= bits(RW0I, 3, 3)
|
|
||||||
//~ ram.W_0.data[4] <= bits(RW0I, 4, 4)
|
|
||||||
//~ ram.W_0.data[5] <= bits(RW0I, 5, 5)
|
|
||||||
//~ ram.W_0.data[6] <= bits(RW0I, 6, 6)
|
|
||||||
//~ ram.W_0.data[7] <= bits(RW0I, 7, 7)
|
|
||||||
//~ ram.W_0.data[8] <= bits(RW0I, 8, 8)
|
|
||||||
//~ ram.W_0.data[9] <= bits(RW0I, 9, 9)
|
|
||||||
//~ ram.W_0.data[10] <= bits(RW0I, 10, 10)
|
|
||||||
//~ ram.W_0.data[11] <= bits(RW0I, 11, 11)
|
|
||||||
//~ ram.W_0.data[12] <= bits(RW0I, 12, 12)
|
|
||||||
//~ ram.W_0.data[13] <= bits(RW0I, 13, 13)
|
|
||||||
//~ ram.W_0.data[14] <= bits(RW0I, 14, 14)
|
|
||||||
//~ ram.W_0.data[15] <= bits(RW0I, 15, 15)
|
|
||||||
//~ ram.W_0.mask[0] <= bits(RW0M, 0, 0)
|
|
||||||
//~ ram.W_0.mask[1] <= bits(RW0M, 1, 1)
|
|
||||||
//~ ram.W_0.mask[2] <= bits(RW0M, 2, 2)
|
|
||||||
//~ ram.W_0.mask[3] <= bits(RW0M, 3, 3)
|
|
||||||
//~ ram.W_0.mask[4] <= bits(RW0M, 4, 4)
|
|
||||||
//~ ram.W_0.mask[5] <= bits(RW0M, 5, 5)
|
|
||||||
//~ ram.W_0.mask[6] <= bits(RW0M, 6, 6)
|
|
||||||
//~ ram.W_0.mask[7] <= bits(RW0M, 7, 7)
|
|
||||||
//~ ram.W_0.mask[8] <= bits(RW0M, 8, 8)
|
|
||||||
//~ ram.W_0.mask[9] <= bits(RW0M, 9, 9)
|
|
||||||
//~ ram.W_0.mask[10] <= bits(RW0M, 10, 10)
|
|
||||||
//~ ram.W_0.mask[11] <= bits(RW0M, 11, 11)
|
|
||||||
//~ ram.W_0.mask[12] <= bits(RW0M, 12, 12)
|
|
||||||
//~ ram.W_0.mask[13] <= bits(RW0M, 13, 13)
|
|
||||||
//~ ram.W_0.mask[14] <= bits(RW0M, 14, 14)
|
|
||||||
//~ ram.W_0.mask[15] <= bits(RW0M, 15, 15)
|
|
||||||
|
|
||||||
//~ module vendor_sram_4 :
|
class Synflops2048x16_noLib extends MacroCompilerSpec with HasSRAMGenerator with HasNoLibTestGenerator with HasSynFlopsTestGenerator {
|
||||||
//~ input clock : Clock
|
override lazy val memDepth = 2048
|
||||||
//~ input RW0A : UInt<11>
|
override lazy val memWidth = 16
|
||||||
//~ input RW0I : UInt<4>
|
|
||||||
//~ output RW0O : UInt<4>
|
|
||||||
//~ input RW0E : UInt<1>
|
|
||||||
//~ input RW0W : UInt<1>
|
|
||||||
//~ input RW0M : UInt<4>
|
|
||||||
|
|
||||||
//~ mem ram :
|
compileExecuteAndTest(mem, None, v, output, true)
|
||||||
//~ data-type => UInt<1>[4]
|
}
|
||||||
//~ depth => 2048
|
|
||||||
//~ read-latency => 0
|
|
||||||
//~ write-latency => 1
|
|
||||||
//~ reader => R_0
|
|
||||||
//~ writer => W_0
|
|
||||||
//~ read-under-write => undefined
|
|
||||||
//~ reg R_0_addr_reg : UInt<11>, clock with :
|
|
||||||
//~ reset => (UInt<1>("h0"), R_0_addr_reg)
|
|
||||||
//~ ram.R_0.clk <= clock
|
|
||||||
//~ ram.R_0.addr <= R_0_addr_reg
|
|
||||||
//~ ram.R_0.en <= RW0E
|
|
||||||
//~ RW0O <= cat(ram.R_0.data[3], cat(ram.R_0.data[2], cat(ram.R_0.data[1], ram.R_0.data[0])))
|
|
||||||
//~ R_0_addr_reg <= mux(RW0E, RW0A, R_0_addr_reg)
|
|
||||||
//~ ram.W_0.clk <= clock
|
|
||||||
//~ ram.W_0.addr <= RW0A
|
|
||||||
//~ ram.W_0.en <= and(RW0E, RW0W)
|
|
||||||
//~ ram.W_0.data[0] <= bits(RW0I, 0, 0)
|
|
||||||
//~ ram.W_0.data[1] <= bits(RW0I, 1, 1)
|
|
||||||
//~ ram.W_0.data[2] <= bits(RW0I, 2, 2)
|
|
||||||
//~ ram.W_0.data[3] <= bits(RW0I, 3, 3)
|
|
||||||
//~ ram.W_0.mask[0] <= bits(RW0M, 0, 0)
|
|
||||||
//~ ram.W_0.mask[1] <= bits(RW0M, 1, 1)
|
|
||||||
//~ ram.W_0.mask[2] <= bits(RW0M, 2, 2)
|
|
||||||
//~ ram.W_0.mask[3] <= bits(RW0M, 3, 3)
|
|
||||||
//~ """
|
|
||||||
//~ compile(mem, None, v, true)
|
|
||||||
//~ execute(Some(mem), None, true, output)
|
|
||||||
//~ }
|
|
||||||
|
|
||||||
//~ class Synflops32x32_2rw extends MacroCompilerSpec {
|
class Synflops8192x16_noLib extends MacroCompilerSpec with HasSRAMGenerator with HasNoLibTestGenerator with HasSynFlopsTestGenerator {
|
||||||
//~ val mem = new File(macroDir, "lib-32x32-2rw.json")
|
override lazy val memDepth = 8192
|
||||||
//~ val v = new File(testDir, "syn_flops_32x32_2rw.v")
|
override lazy val memWidth = 16
|
||||||
//~ val output =
|
|
||||||
//~ """
|
|
||||||
//~ circuit SRAM2RW32x32 :
|
|
||||||
//~ module SRAM2RW32x32 :
|
|
||||||
//~ input CE1 : Clock
|
|
||||||
//~ input A1 : UInt<5>
|
|
||||||
//~ input I1 : UInt<32>
|
|
||||||
//~ output O1 : UInt<32>
|
|
||||||
//~ input CSB1 : UInt<1>
|
|
||||||
//~ input OEB1 : UInt<1>
|
|
||||||
//~ input WEB1 : UInt<1>
|
|
||||||
//~ input CE2 : Clock
|
|
||||||
//~ input A2 : UInt<5>
|
|
||||||
//~ input I2 : UInt<32>
|
|
||||||
//~ output O2 : UInt<32>
|
|
||||||
//~ input CSB2 : UInt<1>
|
|
||||||
//~ input OEB2 : UInt<1>
|
|
||||||
//~ input WEB2 : UInt<1>
|
|
||||||
|
|
||||||
//~ mem ram :
|
compileExecuteAndTest(mem, None, v, output, true)
|
||||||
//~ data-type => UInt<32>
|
}
|
||||||
//~ depth => 32
|
|
||||||
//~ read-latency => 0
|
class Synflops2048x16_depth_Lib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with HasSynFlopsTestGenerator {
|
||||||
//~ write-latency => 1
|
override lazy val memDepth = 2048
|
||||||
//~ reader => R_0
|
override lazy val libDepth = 1024
|
||||||
//~ reader => R_1
|
override lazy val width = 16
|
||||||
//~ writer => W_0
|
|
||||||
//~ writer => W_1
|
compileExecuteAndTest(mem, lib, v, output, true)
|
||||||
//~ read-under-write => undefined
|
}
|
||||||
//~ reg R_0_addr_reg : UInt<5>, CE1 with :
|
|
||||||
//~ reset => (UInt<1>("h0"), R_0_addr_reg)
|
class Synflops2048x64_width_Lib extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleWidthTestGenerator with HasSynFlopsTestGenerator {
|
||||||
//~ ram.R_0.clk <= CE1
|
override lazy val memWidth = 64
|
||||||
//~ ram.R_0.addr <= R_0_addr_reg
|
override lazy val libWidth = 8
|
||||||
//~ ram.R_0.en <= and(not(CSB1), not(OEB1))
|
override lazy val depth = 1024
|
||||||
//~ O1 <= ram.R_0.data
|
|
||||||
//~ R_0_addr_reg <= mux(and(not(CSB1), not(OEB1)), A1, R_0_addr_reg)
|
compileExecuteAndTest(mem, lib, v, output, true)
|
||||||
//~ reg R_1_addr_reg : UInt<5>, CE2 with :
|
}
|
||||||
//~ reset => (UInt<1>("h0"), R_1_addr_reg)
|
|
||||||
//~ ram.R_1.clk <= CE2
|
class Synflops_SplitPorts_Read_Write extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with HasSynFlopsTestGenerator {
|
||||||
//~ ram.R_1.addr <= R_1_addr_reg
|
import mdf.macrolib._
|
||||||
//~ ram.R_1.en <= and(not(CSB2), not(OEB2))
|
|
||||||
//~ O2 <= ram.R_1.data
|
override lazy val memDepth = 2048
|
||||||
//~ R_1_addr_reg <= mux(and(not(CSB2), not(OEB2)), A2, R_1_addr_reg)
|
override lazy val libDepth = 1024
|
||||||
//~ ram.W_0.clk <= CE1
|
override lazy val width = 8
|
||||||
//~ ram.W_0.addr <= A1
|
|
||||||
//~ ram.W_0.en <= and(not(CSB1), not(WEB1))
|
override def generateLibSRAM = SRAMMacro(
|
||||||
//~ ram.W_0.data <= I1
|
macroType=SRAM,
|
||||||
//~ ram.W_0.mask <= UInt<1>("h1")
|
name=lib_name,
|
||||||
//~ ram.W_1.clk <= CE2
|
width=width,
|
||||||
//~ ram.W_1.addr <= A2
|
depth=libDepth,
|
||||||
//~ ram.W_1.en <= and(not(CSB2), not(WEB2))
|
family="1r1w",
|
||||||
//~ ram.W_1.data <= I2
|
ports=Seq(
|
||||||
//~ ram.W_1.mask <= UInt<1>("h1")
|
generateReadPort("innerA", width, libDepth),
|
||||||
//~ """
|
generateWritePort("innerB", width, libDepth)
|
||||||
//~ compile(mem, None, v, true)
|
)
|
||||||
//~ execute(Some(mem), None, true, output)
|
)
|
||||||
//~ }
|
|
||||||
|
override def generateMemSRAM = SRAMMacro(
|
||||||
|
macroType=SRAM,
|
||||||
|
name=mem_name,
|
||||||
|
width=width,
|
||||||
|
depth=memDepth,
|
||||||
|
family="1r1w",
|
||||||
|
ports=Seq(
|
||||||
|
generateReadPort("outerB", width, memDepth),
|
||||||
|
generateWritePort("outerA", width, memDepth)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override def generateHeader =
|
||||||
|
"""
|
||||||
|
circuit target_memory :
|
||||||
|
module target_memory :
|
||||||
|
input outerB_clk : Clock
|
||||||
|
input outerB_addr : UInt<11>
|
||||||
|
output outerB_dout : UInt<8>
|
||||||
|
input outerA_clk : Clock
|
||||||
|
input outerA_addr : UInt<11>
|
||||||
|
input outerA_din : UInt<8>
|
||||||
|
input outerA_write_en : UInt<1>
|
||||||
|
"""
|
||||||
|
|
||||||
|
override def generateBody =
|
||||||
|
"""
|
||||||
|
node outerB_addr_sel = bits(outerB_addr, 10, 10)
|
||||||
|
reg outerB_addr_sel_reg : UInt<1>, outerB_clk with :
|
||||||
|
reset => (UInt<1>("h0"), outerB_addr_sel_reg)
|
||||||
|
outerB_addr_sel_reg <= mux(UInt<1>("h1"), outerB_addr_sel, outerB_addr_sel_reg)
|
||||||
|
node outerA_addr_sel = bits(outerA_addr, 10, 10)
|
||||||
|
inst mem_0_0 of awesome_lib_mem
|
||||||
|
mem_0_0.innerB_clk <= outerA_clk
|
||||||
|
mem_0_0.innerB_addr <= outerA_addr
|
||||||
|
mem_0_0.innerB_din <= bits(outerA_din, 7, 0)
|
||||||
|
mem_0_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h0")))
|
||||||
|
mem_0_0.innerA_clk <= outerB_clk
|
||||||
|
mem_0_0.innerA_addr <= outerB_addr
|
||||||
|
node outerB_dout_0_0 = bits(mem_0_0.innerA_dout, 7, 0)
|
||||||
|
node outerB_dout_0 = outerB_dout_0_0
|
||||||
|
inst mem_1_0 of awesome_lib_mem
|
||||||
|
mem_1_0.innerB_clk <= outerA_clk
|
||||||
|
mem_1_0.innerB_addr <= outerA_addr
|
||||||
|
mem_1_0.innerB_din <= bits(outerA_din, 7, 0)
|
||||||
|
mem_1_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h1")))
|
||||||
|
mem_1_0.innerA_clk <= outerB_clk
|
||||||
|
mem_1_0.innerA_addr <= outerB_addr
|
||||||
|
node outerB_dout_1_0 = bits(mem_1_0.innerA_dout, 7, 0)
|
||||||
|
node outerB_dout_1 = outerB_dout_1_0
|
||||||
|
outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<1>("h0")))
|
||||||
|
"""
|
||||||
|
|
||||||
|
override def generateFooterPorts =
|
||||||
|
"""
|
||||||
|
input innerA_clk : Clock
|
||||||
|
input innerA_addr : UInt<10>
|
||||||
|
output innerA_dout : UInt<8>
|
||||||
|
input innerB_clk : Clock
|
||||||
|
input innerB_addr : UInt<10>
|
||||||
|
input innerB_din : UInt<8>
|
||||||
|
input innerB_write_en : UInt<1>
|
||||||
|
"""
|
||||||
|
|
||||||
|
override def generateFlops =
|
||||||
|
"""
|
||||||
|
mem ram :
|
||||||
|
data-type => UInt<8>
|
||||||
|
depth => 1024
|
||||||
|
read-latency => 1
|
||||||
|
write-latency => 1
|
||||||
|
reader => R_0
|
||||||
|
writer => W_0
|
||||||
|
read-under-write => undefined
|
||||||
|
ram.R_0.clk <= innerA_clk
|
||||||
|
ram.R_0.addr <= innerA_addr
|
||||||
|
ram.R_0.en <= UInt<1>("h1")
|
||||||
|
innerA_dout <= ram.R_0.data
|
||||||
|
ram.W_0.clk <= innerB_clk
|
||||||
|
ram.W_0.addr <= innerB_addr
|
||||||
|
ram.W_0.en <= innerB_write_en
|
||||||
|
ram.W_0.data <= innerB_din
|
||||||
|
ram.W_0.mask <= UInt<1>("h1")
|
||||||
|
"""
|
||||||
|
|
||||||
|
"Non-masked split lib; split mem" should "syn flops fine" in {
|
||||||
|
compileExecuteAndTest(mem, lib, v, output, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Synflops_SplitPorts_MaskedMem_Read_MaskedWrite extends MacroCompilerSpec with HasSRAMGenerator with HasSimpleDepthTestGenerator with HasSynFlopsTestGenerator {
|
||||||
|
import mdf.macrolib._
|
||||||
|
|
||||||
|
override lazy val memDepth = 2048
|
||||||
|
override lazy val libDepth = 1024
|
||||||
|
override lazy val width = 8
|
||||||
|
override lazy val memMaskGran = Some(8)
|
||||||
|
override lazy val libMaskGran = Some(1)
|
||||||
|
|
||||||
|
override def generateLibSRAM = SRAMMacro(
|
||||||
|
macroType=SRAM,
|
||||||
|
name=lib_name,
|
||||||
|
width=width,
|
||||||
|
depth=libDepth,
|
||||||
|
family="1r1w",
|
||||||
|
ports=Seq(
|
||||||
|
generateReadPort("innerA", width, libDepth),
|
||||||
|
generateWritePort("innerB", width, libDepth, libMaskGran)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override def generateMemSRAM = SRAMMacro(
|
||||||
|
macroType=SRAM,
|
||||||
|
name=mem_name,
|
||||||
|
width=width,
|
||||||
|
depth=memDepth,
|
||||||
|
family="1r1w",
|
||||||
|
ports=Seq(
|
||||||
|
generateReadPort("outerB", width, memDepth),
|
||||||
|
generateWritePort("outerA", width, memDepth, memMaskGran)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
override def generateHeader =
|
||||||
|
"""
|
||||||
|
circuit target_memory :
|
||||||
|
module target_memory :
|
||||||
|
input outerB_clk : Clock
|
||||||
|
input outerB_addr : UInt<11>
|
||||||
|
output outerB_dout : UInt<8>
|
||||||
|
input outerA_clk : Clock
|
||||||
|
input outerA_addr : UInt<11>
|
||||||
|
input outerA_din : UInt<8>
|
||||||
|
input outerA_write_en : UInt<1>
|
||||||
|
input outerA_mask : UInt<1>
|
||||||
|
"""
|
||||||
|
|
||||||
|
override def generateBody =
|
||||||
|
"""
|
||||||
|
node outerB_addr_sel = bits(outerB_addr, 10, 10)
|
||||||
|
reg outerB_addr_sel_reg : UInt<1>, outerB_clk with :
|
||||||
|
reset => (UInt<1>("h0"), outerB_addr_sel_reg)
|
||||||
|
outerB_addr_sel_reg <= mux(UInt<1>("h1"), outerB_addr_sel, outerB_addr_sel_reg)
|
||||||
|
node outerA_addr_sel = bits(outerA_addr, 10, 10)
|
||||||
|
inst mem_0_0 of awesome_lib_mem
|
||||||
|
mem_0_0.innerB_clk <= outerA_clk
|
||||||
|
mem_0_0.innerB_addr <= outerA_addr
|
||||||
|
mem_0_0.innerB_din <= bits(outerA_din, 7, 0)
|
||||||
|
mem_0_0.innerB_mask <= cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), bits(outerA_mask, 0, 0))))))))
|
||||||
|
mem_0_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h0")))
|
||||||
|
mem_0_0.innerA_clk <= outerB_clk
|
||||||
|
mem_0_0.innerA_addr <= outerB_addr
|
||||||
|
node outerB_dout_0_0 = bits(mem_0_0.innerA_dout, 7, 0)
|
||||||
|
node outerB_dout_0 = outerB_dout_0_0
|
||||||
|
inst mem_1_0 of awesome_lib_mem
|
||||||
|
mem_1_0.innerB_clk <= outerA_clk
|
||||||
|
mem_1_0.innerB_addr <= outerA_addr
|
||||||
|
mem_1_0.innerB_din <= bits(outerA_din, 7, 0)
|
||||||
|
mem_1_0.innerB_mask <= cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), cat(bits(outerA_mask, 0, 0), bits(outerA_mask, 0, 0))))))))
|
||||||
|
mem_1_0.innerB_write_en <= and(and(outerA_write_en, UInt<1>("h1")), eq(outerA_addr_sel, UInt<1>("h1")))
|
||||||
|
mem_1_0.innerA_clk <= outerB_clk
|
||||||
|
mem_1_0.innerA_addr <= outerB_addr
|
||||||
|
node outerB_dout_1_0 = bits(mem_1_0.innerA_dout, 7, 0)
|
||||||
|
node outerB_dout_1 = outerB_dout_1_0
|
||||||
|
outerB_dout <= mux(eq(outerB_addr_sel_reg, UInt<1>("h0")), outerB_dout_0, mux(eq(outerB_addr_sel_reg, UInt<1>("h1")), outerB_dout_1, UInt<1>("h0")))
|
||||||
|
"""
|
||||||
|
|
||||||
|
override def generateFooterPorts =
|
||||||
|
"""
|
||||||
|
input innerA_clk : Clock
|
||||||
|
input innerA_addr : UInt<10>
|
||||||
|
output innerA_dout : UInt<8>
|
||||||
|
input innerB_clk : Clock
|
||||||
|
input innerB_addr : UInt<10>
|
||||||
|
input innerB_din : UInt<8>
|
||||||
|
input innerB_write_en : UInt<1>
|
||||||
|
input innerB_mask : UInt<8>
|
||||||
|
"""
|
||||||
|
|
||||||
|
override def generateFlops =
|
||||||
|
"""
|
||||||
|
mem ram :
|
||||||
|
data-type => UInt<1>[8]
|
||||||
|
depth => 1024
|
||||||
|
read-latency => 1
|
||||||
|
write-latency => 1
|
||||||
|
reader => R_0
|
||||||
|
writer => W_0
|
||||||
|
read-under-write => undefined
|
||||||
|
ram.R_0.clk <= innerA_clk
|
||||||
|
ram.R_0.addr <= innerA_addr
|
||||||
|
ram.R_0.en <= UInt<1>("h1")
|
||||||
|
innerA_dout <= cat(ram.R_0.data[7], cat(ram.R_0.data[6], cat(ram.R_0.data[5], cat(ram.R_0.data[4], cat(ram.R_0.data[3], cat(ram.R_0.data[2], cat(ram.R_0.data[1], ram.R_0.data[0])))))))
|
||||||
|
ram.W_0.clk <= innerB_clk
|
||||||
|
ram.W_0.addr <= innerB_addr
|
||||||
|
ram.W_0.en <= innerB_write_en
|
||||||
|
ram.W_0.data[0] <= bits(innerB_din, 0, 0)
|
||||||
|
ram.W_0.data[1] <= bits(innerB_din, 1, 1)
|
||||||
|
ram.W_0.data[2] <= bits(innerB_din, 2, 2)
|
||||||
|
ram.W_0.data[3] <= bits(innerB_din, 3, 3)
|
||||||
|
ram.W_0.data[4] <= bits(innerB_din, 4, 4)
|
||||||
|
ram.W_0.data[5] <= bits(innerB_din, 5, 5)
|
||||||
|
ram.W_0.data[6] <= bits(innerB_din, 6, 6)
|
||||||
|
ram.W_0.data[7] <= bits(innerB_din, 7, 7)
|
||||||
|
ram.W_0.mask[0] <= bits(innerB_mask, 0, 0)
|
||||||
|
ram.W_0.mask[1] <= bits(innerB_mask, 1, 1)
|
||||||
|
ram.W_0.mask[2] <= bits(innerB_mask, 2, 2)
|
||||||
|
ram.W_0.mask[3] <= bits(innerB_mask, 3, 3)
|
||||||
|
ram.W_0.mask[4] <= bits(innerB_mask, 4, 4)
|
||||||
|
ram.W_0.mask[5] <= bits(innerB_mask, 5, 5)
|
||||||
|
ram.W_0.mask[6] <= bits(innerB_mask, 6, 6)
|
||||||
|
ram.W_0.mask[7] <= bits(innerB_mask, 7, 7)
|
||||||
|
"""
|
||||||
|
|
||||||
|
"masked split lib; masked split mem" should "syn flops fine" in {
|
||||||
|
compileExecuteAndTest(mem, lib, v, output, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user