| @@ -24,11 +24,11 @@ def javacOptionsVersion(scalaVersion: String): Seq[String] = { | |||
| } | |||
| } | |||
| name := "chisel-module-template" | |||
| name := "chisel intro" | |||
| version := "3.1.0" | |||
| scalaVersion := "2.12.4" | |||
| scalaVersion := "2.12.8" | |||
| crossScalaVersions := Seq("2.11.12", "2.12.4") | |||
| @@ -66,3 +66,8 @@ addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.fu | |||
| testOptions in Test += Tests.Argument(TestFrameworks.ScalaTest, "-eS") | |||
| run := Defaults.runTask(fullClasspath in Runtime, mainClass in run in Compile, runner in run).evaluated | |||
| cancelable in Global := true | |||
| fork := true | |||
| @@ -0,0 +1,5 @@ | |||
| #!/bin/bash | |||
| parallel inkscape -f {} -e pngs/{.} ::: svgOutput/*.svg | |||
| mv ./pngs/svgOutput/* ./pngs/ | |||
| rm -rf ./pngs/svgOutput | |||
| @@ -0,0 +1,2 @@ | |||
| * Hardware description languages | |||
| @@ -139,8 +139,6 @@ | |||
| This is done by creating a test program where the test runner drives inputs and reads outputs from | |||
| the module using what is called a peek poke tester. | |||
| *** Creating a peek poke tester | |||
| #+begin_src scala | |||
| class TheTestRunner(c: MyIncrement) extends PeekPokeTester(c) { | |||
| @@ -35,6 +35,10 @@ object Dependencies { | |||
| "com.github.pathikrit" %% "better-files" % "3.7.0", | |||
| "org.atnos" %% "eff" % "5.2.0" | |||
| "org.atnos" %% "eff" % "5.2.0", | |||
| "org.scala-lang.modules" %% "scala-swing" % "2.1.1", | |||
| "org.apache.xmlgraphics" % "batik-swing" % "1.11" | |||
| )) | |||
| } | |||
| @@ -1 +1 @@ | |||
| sbt.version = 1.1.0 | |||
| sbt.version = 1.2.8 | |||
| @@ -9,7 +9,8 @@ class Vector(val elements: Int) extends Module { | |||
| new Bundle { | |||
| val idx = Input(UInt(32.W)) | |||
| val dataIn = Input(UInt(32.W)) | |||
| val writeEnable = Input(Bool()) | |||
| // val writeEnable = Input(Bool()) | |||
| val readEnable = Input(Bool()) | |||
| val dataOut = Output(UInt(32.W)) | |||
| } | |||
| @@ -19,7 +20,7 @@ class Vector(val elements: Int) extends Module { | |||
| val internalVector = RegInit(VecInit(List.fill(elements)(0.U(32.W)))) | |||
| when(writeEnable){ | |||
| when(io.readEnable){ | |||
| // TODO: | |||
| // When writeEnable is true the content of internalVector at the index specified | |||
| // by idx should be set to the value of io.dataIn | |||
| @@ -9,3 +9,4 @@ object main { | |||
| println(s) | |||
| } | |||
| } | |||
| @@ -1,42 +0,0 @@ | |||
| // class DPCsimulatorSpec extends FlatSpec with Matchers { | |||
| // case class DotProdCalculator(vectorLen: Int, timeStep: Int = 0, accumulator: Int = 0){ | |||
| // def update(inputA: Int, inputB: Int): (Int, Boolean, DotProdCalculator) = { | |||
| // val product = inputA * inputB | |||
| // if(((timeStep + 1) % vectorLen) == 0) | |||
| // (accumulator + product, true, this.copy(timeStep = 0, accumulator = 0)) | |||
| // else | |||
| // (accumulator + product, false, this.copy(timeStep = this.timeStep + 1, accumulator = accumulator + product)) | |||
| // } | |||
| // } | |||
| // val myDPC = DotProdCalculator(4) | |||
| // val dpcStream = Stream.iterate((0, myDPC)){ case(ts, dpc) => | |||
| // val a = scala.util.Random.nextInt(4) | |||
| // val b = scala.util.Random.nextInt(4) | |||
| // val (output, valid, nextDPC) = dpc.update(a, b) | |||
| // val validString = if(valid) "yes" else "no" | |||
| // println(s"at timestep $ts:") | |||
| // println(s"INPUTS:") | |||
| // println(s"inputA: $a, inputB: $b") | |||
| // println(s"OUTPUTS:") | |||
| // println(s"output: $output, valid: $validString\n\n") | |||
| // (ts + 1, nextDPC) | |||
| // }.take(20) | |||
| // behavior of "Dot product simulator" | |||
| // it should "Be shoehorned into a test" in { | |||
| // dpcStream.last | |||
| // } | |||
| // } | |||
| @@ -94,3 +94,42 @@ class MyIncrementManyTest extends FlatSpec with Matchers { | |||
| } should be(true) | |||
| } | |||
| } | |||
| class ChiselConditional() extends Module { | |||
| val io = IO( | |||
| new Bundle { | |||
| val a = Input(UInt(32.W)) | |||
| val b = Input(UInt(32.W)) | |||
| val opSel = Input(Bool()) | |||
| val out = Output(UInt(32.W)) | |||
| } | |||
| ) | |||
| when(io.opSel){ | |||
| io.out := io.a + io.b | |||
| }.otherwise{ | |||
| io.out := io.a - io.b | |||
| } | |||
| } | |||
| class ScalaConditional(opSel: Boolean) extends Module { | |||
| val io = IO( | |||
| new Bundle { | |||
| val a = Input(UInt(32.W)) | |||
| val b = Input(UInt(32.W)) | |||
| val out = Output(UInt(32.W)) | |||
| } | |||
| ) | |||
| if(opSel){ | |||
| io.out := io.a + io.b | |||
| } else { | |||
| io.out := io.a - io.b | |||
| } | |||
| } | |||
| @@ -0,0 +1,51 @@ | |||
| package Ex0 | |||
| import chisel3._ | |||
| import chisel3.experimental._ | |||
| import chisel3.iotesters.PeekPokeTester | |||
| import org.scalatest.{Matchers, FlatSpec} | |||
| import TestUtils._ | |||
| import scala.collection.immutable.{ Vector => _ } | |||
| class SVGSpec extends FlatSpec with Matchers { | |||
| import AdderTests._ | |||
| behavior of "Adder" | |||
| it should "Make some sweet pngs" in { | |||
| // FileUtils.getSvg("Adder") | |||
| wrapTester( | |||
| chisel3.iotesters.Driver(() => new Adder()) { c => | |||
| new AdderTester(c) | |||
| } should be(true) | |||
| ) | |||
| } | |||
| } | |||
| class Adder() extends Module { | |||
| val io = IO( | |||
| new Bundle { | |||
| val reg_a = Output(UInt(32.W)) | |||
| } | |||
| ) | |||
| val reg_a = RegInit(0.U(8.W)) | |||
| reg_a := reg_a + 1.U | |||
| io.reg_a := reg_a | |||
| } | |||
| object AdderTests { | |||
| class AdderTester(c: Adder) extends PeekPokeTesterLogger(c) { | |||
| override def ioLoggers = List(c.io) | |||
| for(ii <- 0 until 10){ | |||
| step(1) | |||
| } | |||
| writeLog | |||
| } | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| package Ex0 | |||
| import chisel3._ | |||
| import chisel3.experimental._ | |||
| import chisel3.iotesters.PeekPokeTester | |||
| import org.scalatest.{Matchers, FlatSpec} | |||
| @@ -42,4 +43,146 @@ object TestUtils { | |||
| case e: Exception => throw e | |||
| } | |||
| } | |||
| abstract class PeekPokeTesterLogger[T <: MultiIOModule](dut: T) extends PeekPokeTester(dut){ | |||
| def ioLoggers: List[chisel3.Bundle] | |||
| import scala.collection.mutable._ | |||
| private val log = ArrayBuffer[LinkedHashMap[String, BigInt]]() | |||
| override def step(n: Int): Unit = { | |||
| ioLoggers.foreach{ ioLogger => log.append(peek(ioLogger)) } | |||
| super.step(n) | |||
| } | |||
| def getLog = log | |||
| def writeLog = { | |||
| import cats.effect.IO | |||
| import SVGRender._ | |||
| val moduleName: String = dut.getClass.getSimpleName | |||
| createSvgs(moduleName, getLog.toList).unsafeRunSync() | |||
| } | |||
| } | |||
| } | |||
| import java.io.File | |||
| import java.nio.file.Path | |||
| import scala.collection.mutable.LinkedHashMap | |||
| import cats.effect.IO | |||
| import cats.implicits._ | |||
| import fs2._ | |||
| import fs2.io | |||
| import fs2.text | |||
| object FileUtils { | |||
| def say(word: Any)(implicit filename: sourcecode.File, line: sourcecode.Line): Unit = { | |||
| val fname = filename.value.split("/").last | |||
| println(Console.YELLOW + s"[${fname}: ${sourcecode.Line()}]" + Console.RESET + s" - $word") | |||
| } | |||
| def getListOfFiles(dir: String): List[File] = | |||
| (new File(dir)).listFiles.filter(_.isFile).toList | |||
| def getListOfFiles(dir: Path): List[File] = | |||
| dir.toFile().listFiles.filter(_.isFile).toList | |||
| def getListOfFolders(dir: String): List[File] = | |||
| (new File(dir)).listFiles.filter(_.isDirectory).toList | |||
| def getListOfFolders(dir: Path): List[File] = | |||
| dir.toFile().listFiles.filter(_.isDirectory).toList | |||
| def getListOfFilesRecursive(dir: String): List[File] = { | |||
| getListOfFiles(dir) ::: getListOfFolders(dir).flatMap(f => | |||
| getListOfFilesRecursive(f.getPath) | |||
| ) | |||
| } | |||
| import java.nio.file.Paths | |||
| import java.util.concurrent.Executors | |||
| def relativeFile(name: String) = { | |||
| new File(getClass.getClassLoader.getResource(name).getPath) | |||
| } | |||
| def getSvgDir: File = | |||
| new File(getClass.getClassLoader.getResource("svgs").getPath) | |||
| def getAllSvgs: List[File] = | |||
| getListOfFilesRecursive(getSvgDir.getPath).filter( f => f.getPath.endsWith(".svg") ) | |||
| import scala.concurrent.ExecutionContext | |||
| val EC = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(10)) | |||
| implicit val cs = IO.contextShift(EC) | |||
| import scala.concurrent.ExecutionContext | |||
| def writeSvg(source: String, cycle: Int): Pipe[IO,String,Unit] = { | |||
| import sys.process._ | |||
| say("pwd".!) | |||
| // val svgDir = getSvgDir.toPath.toString + s"/${source}Output" | |||
| val svgDir = "pwd".!!.filter(_ >= ' ') + s"/svgOutput" | |||
| (new File(svgDir)).mkdir() | |||
| val svgDest = new File(svgDir + s"/$cycle.svg").toPath | |||
| svgStream => svgStream | |||
| .through(text.utf8Encode) | |||
| .through(fs2.io.file.writeAll(svgDest, EC)) | |||
| } | |||
| def getSvg(moduleName: String): Stream[IO, String] = { | |||
| say(getAllSvgs) | |||
| say(moduleName) | |||
| val file = getAllSvgs.filter(_.toPath.toString.contains(moduleName)).head | |||
| io.file.readAll[IO](file.toPath(), EC, 4096) | |||
| .through(text.utf8Decode) | |||
| .through(text.lines) | |||
| } | |||
| } | |||
| import java.io.File | |||
| import java.nio.file.Path | |||
| import scala.collection.mutable.LinkedHashMap | |||
| import chisel3._ | |||
| import chisel3.iotesters.PeekPokeTester | |||
| import chisel3.experimental.MultiIOModule | |||
| object SVGRender { | |||
| import FileUtils._ | |||
| import fs2._ | |||
| import cats.effect.IO | |||
| import scala.collection.mutable.LinkedHashMap | |||
| def editFields(line: String, chiselVals: LinkedHashMap[String,BigInt]): String = | |||
| line.split("(?=>)") | |||
| .flatMap(_.split("(?=<)")) | |||
| .map{ subString => | |||
| if(subString.endsWith("_field")){ | |||
| val name = subString.dropRight(6) | |||
| val chiselVal = chiselVals.lift(name.drop(1).toLowerCase).map(_.toString).getOrElse("UNKNOWN") | |||
| s"$name = $chiselVal" | |||
| } | |||
| else | |||
| subString | |||
| }.mkString + "\n" | |||
| def editSvg(fieldValues: LinkedHashMap[String,BigInt]): Pipe[IO, String, String] = | |||
| _.map(line => editFields(line, fieldValues)) | |||
| def createSvgs(moduleName: String, snapshots: List[LinkedHashMap[String,BigInt]]): IO[Unit] = { | |||
| val svgSinks: List[Pipe[IO, String, Unit]] = snapshots.zipWithIndex.map{ case(lhm, idx) => | |||
| editSvg(lhm) andThen FileUtils.writeSvg(moduleName, idx) | |||
| } | |||
| getSvg(moduleName).broadcastTo(svgSinks:_*).compile.drain | |||
| } | |||
| } | |||
| @@ -1,6 +1,7 @@ | |||
| package Ex0 | |||
| import chisel3._ | |||
| import chisel3.experimental._ | |||
| import chisel3.iotesters.PeekPokeTester | |||
| import org.scalatest.{Matchers, FlatSpec} | |||
| import TestUtils._ | |||
| @@ -15,6 +16,7 @@ class VectorSpec extends FlatSpec with Matchers { | |||
| behavior of "Vector" | |||
| it should "Not read data when read enable is false" in { | |||
| // FileUtils.getSvg("Adder") | |||
| wrapTester( | |||
| chisel3.iotesters.Driver(() => new Vector(elements)) { c => | |||
| new ReadEnable(c) | |||
| @@ -22,25 +24,26 @@ class VectorSpec extends FlatSpec with Matchers { | |||
| ) | |||
| } | |||
| it should "Update its registers when read enable is true" in { | |||
| wrapTester( | |||
| chisel3.iotesters.Driver(() => new Vector(elements)) { c => | |||
| new UpdatesData(c) | |||
| } should be(true) | |||
| ) | |||
| } | |||
| it should "Retain its data once read enable is set to false" in { | |||
| wrapTester( | |||
| chisel3.iotesters.Driver(() => new Vector(elements)) { c => | |||
| new UpdatesData(c) | |||
| } should be(true) | |||
| ) | |||
| } | |||
| // it should "Update its registers when read enable is true" in { | |||
| // wrapTester( | |||
| // chisel3.iotesters.Driver(() => new Vector(elements)) { c => | |||
| // new UpdatesData(c) | |||
| // } should be(true) | |||
| // ) | |||
| // } | |||
| // it should "Retain its data once read enable is set to false" in { | |||
| // wrapTester( | |||
| // chisel3.iotesters.Driver(() => new Vector(elements)) { c => | |||
| // new RetainsData(c) | |||
| // } should be(true) | |||
| // ) | |||
| // } | |||
| } | |||
| object VectorTests { | |||
| object VectorTests { | |||
| class ReadEnable(c: Vector) extends PeekPokeTester(c) { | |||
| poke(c.io.dataIn, 123) | |||
| @@ -0,0 +1,143 @@ | |||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | |||
| <svg | |||
| xmlns:dc="http://purl.org/dc/elements/1.1/" | |||
| xmlns:cc="http://creativecommons.org/ns#" | |||
| xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||
| xmlns:svg="http://www.w3.org/2000/svg" | |||
| xmlns="http://www.w3.org/2000/svg" | |||
| xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||
| xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||
| width="210mm" | |||
| height="297mm" | |||
| viewBox="0 0 210 297" | |||
| version="1.1" | |||
| id="svg8" | |||
| inkscape:version="0.92.4 (unknown)" | |||
| sodipodi:docname="svg_test3.svg"> | |||
| <defs | |||
| id="defs2"> | |||
| <inkscape:path-effect | |||
| is_visible="true" | |||
| id="path-effect1515" | |||
| effect="spiro" /> | |||
| <inkscape:path-effect | |||
| effect="spiro" | |||
| id="path-effect1494" | |||
| is_visible="true" /> | |||
| </defs> | |||
| <sodipodi:namedview | |||
| id="base" | |||
| pagecolor="#ffffff" | |||
| bordercolor="#666666" | |||
| borderopacity="1.0" | |||
| inkscape:pageopacity="0.0" | |||
| inkscape:pageshadow="2" | |||
| inkscape:zoom="1.4" | |||
| inkscape:cx="489.50694" | |||
| inkscape:cy="789.09773" | |||
| inkscape:document-units="mm" | |||
| inkscape:current-layer="layer1" | |||
| showgrid="false" | |||
| inkscape:window-width="1916" | |||
| inkscape:window-height="1149" | |||
| inkscape:window-x="2280" | |||
| inkscape:window-y="400" | |||
| inkscape:window-maximized="0" /> | |||
| <metadata | |||
| id="metadata5"> | |||
| <rdf:RDF> | |||
| <cc:Work | |||
| rdf:about=""> | |||
| <dc:format>image/svg+xml</dc:format> | |||
| <dc:type | |||
| rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||
| <dc:title></dc:title> | |||
| </cc:Work> | |||
| </rdf:RDF> | |||
| </metadata> | |||
| <g | |||
| inkscape:label="Layer 1" | |||
| inkscape:groupmode="layer" | |||
| id="layer1"> | |||
| <rect | |||
| style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79374999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |||
| id="rect815" | |||
| width="42.228577" | |||
| height="35.546844" | |||
| x="33.408691" | |||
| y="25.988699" /> | |||
| <path | |||
| style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79374999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |||
| d="M 33.408691,25.988699 H 75.637268 V 61.535543 H 61.905124 L 54.52298,55.676912 47.140835,61.535543 H 33.408691 Z" | |||
| id="rect1510" | |||
| inkscape:connector-curvature="0" | |||
| sodipodi:nodetypes="cccccccc" /> | |||
| <path | |||
| style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.79374999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" | |||
| d="m 46.931991,88.529769 h 24.78925 L 85.927158,99.1131 100.13308,88.529769 h 24.78925 L 114.33899,117.39488 H 57.515325 Z" | |||
| id="rect1489" | |||
| inkscape:connector-curvature="0" | |||
| sodipodi:nodetypes="cccccccc" /> | |||
| <path | |||
| style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.06500006;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | |||
| d="M 57.997486,61.535545 V 88.529767" | |||
| id="path1492" | |||
| inkscape:connector-curvature="0" | |||
| inkscape:path-effect="#path-effect1494" | |||
| inkscape:original-d="m 57.997486,61.535545 c 2.65e-4,8.997809 2.65e-4,17.995884 0,26.994222" | |||
| transform="translate(7.9375,-0.1889881)" /> | |||
| <path | |||
| style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.065;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" | |||
| d="m 86.328056,117.12761 v 21.9161 H 153.67998 V 44.430296 H 75.370006" | |||
| id="path1500" | |||
| inkscape:connector-curvature="0" /> | |||
| <flowRoot | |||
| xml:space="preserve" | |||
| id="Reg_A" | |||
| style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.0000002px;line-height:125%;font-family:Verdana;-inkscape-font-specification:'Verdana, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;" | |||
| transform="scale(0.26458333)" | |||
| inkscape:label="Reg_A_value"><flowRegion | |||
| id="flowRegion1504" | |||
| style="-inkscape-font-specification:'Verdana, Normal';font-family:Verdana;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:16.0000002px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"><rect | |||
| id="rect1506" | |||
| width="138.39091" | |||
| height="21.213207" | |||
| x="139.40105" | |||
| y="122.97374" | |||
| style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.0000002px;font-family:Verdana;-inkscape-font-specification:'Verdana, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr;text-anchor:start;" /></flowRegion><flowPara | |||
| id="flowPara1615">Reg_A = 0</flowPara></flowRoot> <path | |||
| transform="translate(49.420387,-0.1889881)" | |||
| inkscape:original-d="m 57.997486,61.535545 c 2.65e-4,8.997809 2.65e-4,17.995884 0,26.994222" | |||
| inkscape:path-effect="#path-effect1515" | |||
| inkscape:connector-curvature="0" | |||
| id="path1513" | |||
| d="M 57.997486,61.535545 V 88.529767" | |||
| style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1.06500006;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> | |||
| <flowRoot | |||
| xml:space="preserve" | |||
| id="flowRoot1517" | |||
| style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:37.33333206px;line-height:125%;font-family:Verdana;-inkscape-font-specification:'Verdana, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | |||
| transform="scale(0.26458333)"><flowRegion | |||
| id="flowRegion1519"><rect | |||
| id="rect1521" | |||
| width="92.5" | |||
| height="38.57143" | |||
| x="416.42856" | |||
| y="222.16254" /></flowRegion><flowPara | |||
| id="flowPara1523">1</flowPara></flowRoot> <flowRoot | |||
| xml:space="preserve" | |||
| id="flowRoot1525" | |||
| style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:37.33333206px;line-height:125%;font-family:Verdana;-inkscape-font-specification:'Verdana, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" | |||
| transform="scale(0.26458333)"><flowRegion | |||
| id="flowRegion1527"><rect | |||
| id="rect1529" | |||
| width="117.14286" | |||
| height="74.64286" | |||
| x="416.07144" | |||
| y="219.66254" /></flowRegion><flowPara | |||
| id="flowPara1531" | |||
| style="-inkscape-font-specification:'Verdana, Normal';font-family:Verdana;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;font-size:21.3333336px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal">1</flowPara></flowRoot> </g> | |||
| </svg> | |||