bitstream.compiler.Handlers.scala Maven / Gradle / Ivy
The newest version!
package bitstream.compiler
trait NodeHandler {
protected var id: Int
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String)
}
/*
* Node Handlers
* -------------
* Intended usage:
* - Compile the Bitstream JAR file along with your source
* - Add `import bitstream.compiler.NodeHandlers._` to your source
* - Instantiate a handler with `var addHandler = new AddHandler()`
* - Use the handler with `addHandler.create(...)` passing in and out the global netlist
*/
object NodeHandlers {
val stdComment = "// Autogenerated by Bitstream DSL compiler"
def addFeedback(name: String, init: String, decorr: String, input: String, size: Tuple2[Int, Int], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Update netlist
newNetList.addWire(input, size, true, false)
newNetList.addWire(name, size, true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN feedback${input}
|assign ${input}_p = switch_inputs ? ${decorr}_p : ${init}_p;
|assign ${input}_m = switch_inputs ? ${decorr}_m : ${init}_m;
|// END feedback${input}
""".stripMargin
(newNetList, outputString)
}
def addModuleInstance(name: String, module: String, params: List[String],
inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes.dropRight(1)).toMap) {
newNetList.addWire(name, size, false, false)
}
// Add output to wire
newNetList.addWire(output, sizes.last, false, false)
// Get explicit parameters names
val builder = (list: List[Tuple2[String, String]], p: String) =>
list ++ List((p.split("_").last, p))
val explicitParams = params.foldLeft(List[Tuple2[String, String]]())(builder)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN $name
|$module #(""".stripMargin
for (param <- explicitParams.dropRight(1)) {
outputString = outputString + s"""
| .${param._1}(${param._2}),""".stripMargin
}
outputString = outputString + s"""
| .${explicitParams.last._1}(${explicitParams.last._2})
| ) $name (""".stripMargin
outputString = outputString + s"""
| CLK, nRST,""".stripMargin
for (input <- inputs) {
outputString = outputString + s"""
| $input,""".stripMargin
}
outputString = outputString + s"""
| $output
| );
|// END $name
""".stripMargin
(newNetList, outputString)
}
def printTopLevel(modName: String, netList: Netlist, bitWidth: String, intWidth: String):
String = {
// Add top level name
var outputString:String = s"module $modName(CLK, nRST, "
// Add inputs
outputString =
netList.inputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
case Net(true, _, _, _) => str + s"${entry._1}_p " + s"${entry._1}_m "
case Net(false, _, _, _) => str + s"${entry._1} "
}).replaceAll(" ", ", ")
// Add outputs
outputString =
netList.outputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
case Net(true, _, _, _) => str + s"${entry._1}_p " + s"${entry._1}_m "
case Net(false, _, _, _) => str + s"${entry._1} "
}).trim.replaceAll(" ", ", ")
outputString = outputString + ");\n\n"
// Add parameters
if (bitWidth != "") {
outputString = outputString + s"parameter BIT_WIDTH = $bitWidth;\n"
outputString = outputString + s"parameter INT_WIDTH = $intWidth;\n"
}
outputString = outputString + "parameter WINDOW_LEN = 100000;\n"
outputString = outputString + "parameter TICK_COUNTER_SIZE = $clog2(WINDOW_LEN);\n\n"
// Add CLK and nRST
outputString = outputString + "input CLK, nRST;\n"
// Add netlist
outputString =
netList.inputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
case Net(true, _, 1, 1) => str + s"input ${entry._1}_p, ${entry._1}_m;\n"
case Net(false, _, 1, 1) => str + s"input ${entry._1};\n"
case Net(true, _, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"input [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
}
case Net(false, _, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"input [($widthStr*$depth)-1:0] ${entry._1};\n"
}
})
outputString =
netList.outputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
case Net(true, false, 1, 1) => str + s"output ${entry._1}_p, ${entry._1}_m;\n"
case Net(false, false, 1, 1) => str + s"output ${entry._1};\n"
case Net(true, false, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"output [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
}
case Net(false, false, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"output [($widthStr*$depth)-1:0] ${entry._1};\n"
}
case Net(_, _, _, _) => str
})
outputString =
netList.outputs.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
case Net(true, true, 1, 1) => str + s"output reg ${entry._1}_p, ${entry._1}_m;\n"
case Net(false, true, 1, 1) => str + s"output reg ${entry._1};\n"
case Net(true, true, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"output reg [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
}
case Net(false, true, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"output reg [($widthStr*$depth)-1:0] ${entry._1};\n"
}
case Net(_, _, _, _) => str
})
outputString =
netList.wires.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
case Net(true, true, 1, 1) => str + s"reg ${entry._1}_p, ${entry._1}_m;\n"
case Net(false, true, 1, 1) => str + s"reg ${entry._1};\n"
case Net(true, true, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"reg [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
}
case Net(false, true, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"reg [($widthStr*$depth)-1:0] ${entry._1};\n"
}
case Net(_, _, _, _) => str
})
outputString =
netList.wires.foldLeft(outputString)((str: String, entry: Tuple2[String, Net]) => entry._2 match {
case Net(true, false, 1, 1) => str + s"wire ${entry._1}_p, ${entry._1}_m;\n"
case Net(false, false, 1, 1) => str + s"wire ${entry._1};\n"
case Net(true, false, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"wire [($widthStr*$depth)-1:0] ${entry._1}_p, ${entry._1}_m;\n"
}
case Net(false, false, width, depth) => {
val widthStr = if (width < 0) "BIT_WIDTH" else width.toString
str + s"wire [($widthStr*$depth)-1:0] ${entry._1};\n"
}
case Net(_, _, _, _) => str
})
outputString
}
def printUserParams(params: Map[String, String]): String = {
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN User-defined module parameters
|""".stripMargin
for ((param, value) <- params) {
outputString = outputString + s"parameter $param = $value;\n"
}
outputString = outputString + "// END User-defined module parameters\n\n"
outputString
}
def printInputSwitch(): String = {
var outputString = "\nreg [TICK_COUNTER_SIZE-1:0] tick_counter, next_tick_counter;\n"
outputString = outputString + "wire switch_inputs;\n\n"
outputString = outputString +
s"""|// update tick counter
|always @(posedge CLK) begin
| if (!nRST) begin
| tick_counter <= {TICK_COUNTER_SIZE{1'b0}};
| end
| else begin
| tick_counter <= next_tick_counter;
| end
|end
|// increment the tick counter
|always @(tick_counter) begin
| if (switch_inputs == 1'b0) next_tick_counter <= tick_counter + {{(TICK_COUNTER_SIZE-1){1'b0}}, 1'b1};
| else next_tick_counter <= tick_counter;
|end
|assign switch_inputs = (tick_counter >= WINDOW_LEN) ? 1'b1 : 1'b0;
""".stripMargin
outputString = outputString + "\n\n"
outputString
}
class SAssignHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add output to wire
newNetList.addWire(output, sizes.head, true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN sassign${id}
|assign ${output}_p = ${inputs(0)}_p;
|assign ${output}_m = ${inputs(0)}_m;
|// END sassign${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DAssignHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, false, false)
}
// Add output to wire
newNetList.addWire(output, sizes.head, false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN dassign${id}
|assign $output = ${inputs(0)};
|// END dassign${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class SAddHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add internal nets to netlist
newNetList.addWire(s"add${id}_addPP", sizes.last, false, false)
newNetList.addWire(s"add${id}_addMM", sizes.last, false, false)
// Add outputs to netlist
newNetList.addWire(output, sizes.last, true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN add${id}
|stoch_add_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) add${id}_PP (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_p),
| .B(${inputs(1)}_p),
| .Y(add${id}_addPP)
| );
|stoch_add_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) add${id}_MM (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_m),
| .B(${inputs(1)}_m),
| .Y(add${id}_addMM)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) add${id}_P (
| .CLK(CLK),
| .nRST(nRST),
| .A(add${id}_addPP),
| .B(add${id}_addMM),
| .Y(${output}_p)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) add${id}_M (
| .CLK(CLK),
| .nRST(nRST),
| .A(add${id}_addMM),
| .B(add${id}_addPP),
| .Y(${output}_m)
| );
|// END add${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class SSubHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add internal nets to netlist
newNetList.addWire(s"sub${id}_addPM", sizes.last, false, false)
newNetList.addWire(s"sub${id}_addMP", sizes.last, false, false)
// Add outputs to netlist
newNetList.addWire(output, sizes.last, true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN sub${id}
|stoch_add_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) sub${id}_PM (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_p),
| .B(${inputs(1)}_p),
| .Y(sub${id}_addPM)
| );
|stoch_add_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) sub${id}_MP (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_m),
| .B(${inputs(1)}_m),
| .Y(sub${id}_addMP)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) sub${id}_P (
| .CLK(CLK),
| .nRST(nRST),
| .A(sub${id}_addPM),
| .B(sub${id}_addMP),
| .Y(${output}_p)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS(${sizes.last._1}),
| .NUM_COLS(${sizes.last._2})
| ) sub${id}_M (
| .CLK(CLK),
| .nRST(nRST),
| .A(sub${id}_addMP),
| .B(sub${id}_addPM),
| .Y(${output}_m)
| );
|// END sub${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class SMatrixMultiplyHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add internal nets to netlist
val (m, n) = sizes(0)
val (_, p) = sizes(1)
newNetList.addWire(s"mmult${id}_multPP", (m, p), false, false)
newNetList.addWire(s"mmult${id}_multPM", (m, p), false, false)
newNetList.addWire(s"mmult${id}_multMP", (m, p), false, false)
newNetList.addWire(s"mmult${id}_multMM", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subPPPM", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subPMPP", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subMPMM", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subMMMP", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subPP", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subMP", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subPM", (m, p), false, false)
newNetList.addWire(s"mmult${id}_subMM", (m, p), false, false)
// Add outputs to netlist
newNetList.addWire(output, (m, p), true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN mmult${id}
|stoch_matrix_mult #(
| .NUM_ROWS($m),
| .NUM_MID($n),
| .NUM_COLS($p)
| ) mmult${id}_mPP (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_p),
| .B(${inputs(1)}_p),
| .Y(mmult${id}_multPP)
| );
|stoch_matrix_mult #(
| .NUM_ROWS($m),
| .NUM_MID($n),
| .NUM_COLS($p)
| ) mmult${id}_mPM (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_p),
| .B(${inputs(1)}_m),
| .Y(mmult${id}_multPM)
| );
|stoch_matrix_mult #(
| .NUM_ROWS($m),
| .NUM_MID($n),
| .NUM_COLS($p)
| ) mmult${id}_mMP (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_m),
| .B(${inputs(1)}_p),
| .Y(mmult${id}_multMP)
| );
|stoch_matrix_mult #(
| .NUM_ROWS($m),
| .NUM_MID($n),
| .NUM_COLS($p)
| ) mmult${id}_mMM (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_m),
| .B(${inputs(1)}_m),
| .Y(mmult${id}_multMM)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_PPPM (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_multPP),
| .B(mmult${id}_multPM),
| .Y(mmult${id}_subPPPM)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_PMPP (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_multPM),
| .B(mmult${id}_multPP),
| .Y(mmult${id}_subPMPP)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_MPMM (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_multMP),
| .B(mmult${id}_multMM),
| .Y(mmult${id}_subMPMM)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_MMMP (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_multMM),
| .B(mmult${id}_multMP),
| .Y(mmult${id}_subMMMP)
| );
""".stripMargin
outputString = outputString + s"""|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_sPP (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_subPPPM),
| .B(mmult${id}_subMMMP),
| .Y(mmult${id}_subPP)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_sMP (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_subMPMM),
| .B(mmult${id}_subPMPP),
| .Y(mmult${id}_subMP)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_sPM (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_subPMPP),
| .B(mmult${id}_subMPMM),
| .Y(mmult${id}_subPM)
| );
|stoch_sat_sub_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_sMM (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_subMMMP),
| .B(mmult${id}_subPPPM),
| .Y(mmult${id}_subMM)
| );
|stoch_add_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_P (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_subPP),
| .B(mmult${id}_subPM),
| .Y(${output}_p)
| );
|stoch_add_mat #(
| .NUM_ROWS($m),
| .NUM_COLS($p)
| ) mmult${id}_M (
| .CLK(CLK),
| .nRST(nRST),
| .A(mmult${id}_subMP),
| .B(mmult${id}_subMM),
| .Y(${output}_m)
| );
|// END mmult${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class SDivHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Determine new names for netlist
var newNames = inputs :+ output
// Check sizes
var newSizes = sizes
var outputString = ""
(sizes(0)._1, sizes(0)._2, sizes(1)._1, sizes(1)._2) match {
case (1, 1, 1, 1) => {
newSizes = newSizes :+ (1, 1)
outputString = s"""
|$stdComment
|// Start div${id}
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(1),
| .NUM_COLS(1)
| ) div${id}_P (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_p),
| .B(${inputs(1)}_p),
| .Y(${output}_p)
| );
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(1),
| .NUM_COLS(1)
| ) div${id}_M (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_m),
| .B(${inputs(1)}_p),
| .Y(${output}_m)
| );
|// END div${id}
""".stripMargin
}
case (1, 1, _, _) => {
newSizes = newSizes :+ sizes.last
outputString = s"""
|$stdComment
|// Start div${id}
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(${sizes(1)._1}),
| .NUM_COLS(${sizes(1)._2})
| ) div${id}_P (
| .CLK(CLK),
| .nRST(nRST),
| .A({${sizes(1)._1 * sizes(1)._2}{${inputs(0)}_p}}),
| .B(${inputs(1)}_p),
| .Y(${output}_p)
| );
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(${sizes(1)._1}),
| .NUM_COLS(${sizes(1)._2})
| ) div${id}_M (
| .CLK(CLK),
| .nRST(nRST),
| .A({${sizes(1)._1 * sizes(1)._2}{${inputs(0)}_m}}),
| .B(${inputs(1)}_p),
| .Y(${output}_m)
| );
|// END div${id}
""".stripMargin
}
case (_, _, 1, 1) => {
newSizes = newSizes :+ sizes.head
outputString = s"""
|$stdComment
|// Start div${id}
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(${sizes(0)._1}),
| .NUM_COLS(${sizes(0)._2})
| ) div${id}_P (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_p),
| .B({${sizes(0)._1 * sizes(0)._2}{${inputs(1)}_p}}),
| .Y(${output}_p)
| );
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(${sizes(0)._1}),
| .NUM_COLS(${sizes(0)._2})
| ) div${id}_M (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_m),
| .B({${sizes(0)._1 * sizes(0)._2}{${inputs(1)}_p}}),
| .Y(${output}_m)
| );
|// END div${id}
""".stripMargin
}
case _ => {
newSizes = newSizes :+ sizes.last
outputString = s"""
|$stdComment
|// Start div${id}
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(${sizes(0)._1}),
| .NUM_COLS(${sizes(0)._2})
| ) div${id}_P (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_p),
| .B(${inputs(1)}_p),
| .Y(${output}_p)
| );
|stoch_div_mat #(
| .COUNTER_SIZE(8),
| .NUM_ROWS(${sizes(0)._1}),
| .NUM_COLS(${sizes(0)._2})
| ) div${id}_M (
| .CLK(CLK),
| .nRST(nRST),
| .A(${inputs(0)}_m),
| .B(${inputs(1)}_p),
| .Y(${output}_m)
| );
|// END div${id}
""".stripMargin
}
}
// Update netlist
for ((name, size) <- (newNames zip newSizes).toMap) {
newNetList.addWire(name, size, true, false)
}
id += 1
(newNetList, outputString)
}
}
class SFixedGainDivHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
newNetList.addWire(inputs(0), sizes(0), true, false)
// Add outputs to netlist
newNetList.addWire(output, sizes.head, true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN fdiv${id}
|stoch_fixed_gain_div_mat #(
| .COUNTER_SIZE(8),
| .GAIN(${inputs(1)}),
| .NUM_ROWS(${sizes(0)._1}),
| .NUM_COLS(${sizes(0)._2})
| ) fdiv${id}_P (
| .CLK (CLK),
| .nRST (nRST),
| .A (${inputs(0)}_p),
| .Y (${output}_p)
| );
|stoch_fixed_gain_div_mat #(
| .COUNTER_SIZE(8),
| .GAIN(${inputs(1)}),
| .NUM_ROWS(${sizes(0)._1}),
| .NUM_COLS(${sizes(0)._2})
| ) fdiv${id}_M (
| .CLK (CLK),
| .nRST (nRST),
| .A (${inputs(0)}_m),
| .Y (${output}_m)
| );
|// END fdiv${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class SL2NormHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add outputs to netlist
newNetList.addWire(output, (1, 1), true, false)
val m = if (sizes.head._1 == 1) sizes.head._2 else sizes.head._1
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN l2norm${id}
|stoch_l2_norm #(
| .COUNTER_SIZE(8),
| .VEC_LEN($m)
| ) l2norm${id} (
| .CLK (CLK),
| .nRST (nRST),
| .up (${inputs(0)}_p),
| .un (${inputs(0)}_m),
| .y (${output}_p)
| );
|assign ${output}_m = 1'b0;
|// END l2norm${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class SSqrtHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add outputs to netlist
newNetList.addWire(output, (1, 1), true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN sqrt${id}
|stoch_square_root #(
| .COUNTER_SIZE(10)
| ) sqrt${id} (
| .CLK (CLK),
| .nRST (nRST),
| .up (${inputs(0)}_p),
| .un (${inputs(0)}_m),
| .y (${output}_p)
| );
|assign ${output}_m = 1'b0;
|// END sqrt${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class TransposeHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add outputs to netlist
newNetList.addWire(output, sizes.last, true, true)
// Redeclare integers?
val intStr = if (id > 0) "" else "integer i, j;"
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN transpose${id}
|$intStr
|always @(*) begin
| for (i = 0; i < ${sizes.head._1}; i = i + 1) begin
| for (j = 0; j < ${sizes.head._2}; j = j + 1) begin
| ${output}_p[(j*${sizes.head._1}) + i] <= ${inputs(0)}_p[(i*${sizes.head._2}) + j];
| ${output}_m[(j*${sizes.head._1}) + i] <= ${inputs(0)}_m[(i*${sizes.head._2}) + j];
| end
| end
|end
|// END transpose${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class SDecorrelatorHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, true, false)
}
// Add outputs to netlist
newNetList.addWire(output, sizes.last, true, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN decorr${id}
|stoch_decorr_mat #(
| .COUNTER_SIZE(8),
| .STEP_VAL(16),
| .NUM_ROWS(${sizes.head._1}),
| .NUM_COLS(${sizes.head._1})
| ) decorr${id}_P (
| .CLK (CLK),
| .nRST (nRST),
| .A (${inputs(0)}_p),
| .Y (${output}_p)
| );
|stoch_decorr_mat #(
| .COUNTER_SIZE(8),
| .STEP_VAL(16),
| .NUM_ROWS(${sizes.head._1}),
| .NUM_COLS(${sizes.head._1})
| ) decorr${id}_M (
| .CLK (CLK),
| .nRST (nRST),
| .A (${inputs(0)}_m),
| .Y (${output}_m)
| );
|// END decorr${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DAddHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN d_add${id}
|determ_add #(
| .BIT_WIDTH(BIT_WIDTH),
| .INT_WIDTH(INT_WIDTH)
| ) d_add${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END d_add${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DSubHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN d_sub${id}
|determ_sub #(
| .BIT_WIDTH(BIT_WIDTH),
| .INT_WIDTH(INT_WIDTH)
| ) d_sub${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END d_sub${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DMultHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN d_mult${id}
|determ_mult d_mult${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END d_mult${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DAddFxpHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN d_mult_fxp${id}
|determ_add_fxp #(
| .BIT_WIDTH(BIT_WIDTH),
| .INT_WIDTH(INT_WIDTH)
| ) d_add_fxp${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END d_add_fxp${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DSubAFxpHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN d_mult_fxp${id}
|determ_suba_fxp #(
| .BIT_WIDTH(BIT_WIDTH),
| .INT_WIDTH(INT_WIDTH)
| ) d_suba_fxp${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END d_suba_fxp${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DSubBFxpHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN d_mult_fxp${id}
|determ_subb_fxp #(
| .BIT_WIDTH(BIT_WIDTH),
| .INT_WIDTH(INT_WIDTH)
| ) d_subb_fxp${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END d_subb_fxp${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DMultFxpHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN d_mult_fxp${id}
|determ_mult_fxp #(
| .BIT_WIDTH(BIT_WIDTH)
| ) d_mult_fxp${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END d_mult_fxp${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class FxpAddHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN f_add${id}
|fxp_add #(
| .BIT_WIDTH(BIT_WIDTH)
| ) f_add${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END f_add${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class FxpSubHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN f_sub${id}
|fxp_sub #(
| .BIT_WIDTH(BIT_WIDTH)
| ) f_sub${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END f_sub${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class FxpMultHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (-1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN f_mult${id}
|fxp_mult #(
| .BIT_WIDTH(BIT_WIDTH),
| .INT_WIDTH(INT_WIDTH)
| ) f_mult${id} (
| .a(${inputs(0)}),
| .b(${inputs(1)}),
| .y($output)
| );
|// END f_mult${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
class DelayBufferHandler extends NodeHandler {
protected var id = 0
private var netMap: Map[String, Tuple3[String, String, String]] = Map()
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN delay_buff${id}
|delay_buffer #(
| .DELAY(${inputs(1)})
| ) delay_buff${id} (
| .CLK(CLK),
| .nRST(nRST),
| .x(${inputs(0)}),
| .y($output)
| );
|// END delay_buff${id}
""".stripMargin
id += 1
(netList, outputString)
}
def createAll(): String = {
var outStr = ""
for ((name, (input, output, delay)) <- netMap) {
this.create(List(input, delay), output, List(), new Netlist())
match {case (list, str) => outStr += str}
}
outStr
}
def addPop(name: String, netName: String, size: Tuple2[Int, Int], netList: Netlist):
Netlist = {
// Create copy of netlist
var newNetList = netList
// Add wire to netlist
newNetList.addWire(netName, size, false, false)
// Add wire to map
if (netMap contains name) {
var value = netMap(name)
netMap += (name -> (value._1, netName, value._3))
} else netMap += (name -> ("", netName, ""))
newNetList
}
def addPush(name: String, netName: String, size: Tuple2[Int, Int], netList: Netlist):
Netlist = {
// Create copy of netlist
var newNetList = netList
// Add wire to netlist
newNetList.addWire(netName, size, false, false)
// Add wire to map
if (netMap contains name) {
var value = netMap(name)
netMap += (name -> (netName, value._2, value._3))
} else netMap += (name -> (netName, "", ""))
newNetList
}
def getBufferNames: List[String] = netMap.keySet.toList
def setDelay(names: List[String], delays: List[String]): Unit = {
for ((name, delay) <- (names zip delays).toMap) {
// Set delay
if (netMap contains name) {
var value = netMap(name)
netMap += (name -> (value._1, value._2, delay))
} else netMap += (name -> ("", "", delay))
}
}
}
class SDMHandler extends NodeHandler {
protected var id = 0
def create(inputs: List[String], output: String, sizes: List[Tuple2[Int, Int]], netList: Netlist):
(Netlist, String) = {
// Create copy of netlist
var newNetList = netList
// Add inputs to netlist
for ((name, size) <- (inputs zip sizes).toMap
if !(name matches """[\-(?:BITWIDTH_REPLACE)\d\.\'bhdo]+""") && size != (-1, -1)) {
newNetList.addWire(name, size, false, false)
}
// Add outputs to netlist
newNetList.addWire(output, (1, 1), false, false)
// Create Verilog string
var outputString = s"""
|$stdComment
|// BEGIN sdm${id}
|sdm #(
| .BIT_WIDTH(BIT_WIDTH),
| .INT_WIDTH(INT_WIDTH)
| ) sdm${id} (
| .CLK(CLK),
| .nRST(nRST),
| .x(${inputs(0)}),
| .y($output)
| );
|// END sdm${id}
""".stripMargin
id += 1
(newNetList, outputString)
}
}
}