Library of reusable VHDL components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

406 lines
14 KiB

  1. --
  2. -- File Name: TextUtilPkg.vhd
  3. -- Design Unit Name: TextUtilPkg
  4. -- Revision: STANDARD VERSION
  5. --
  6. -- Maintainer: Jim Lewis email: jim@synthworks.com
  7. -- Contributor(s):
  8. -- Jim Lewis jim@synthworks.com
  9. --
  10. --
  11. -- Description:
  12. -- Shared Utilities for handling text files
  13. --
  14. --
  15. -- Developed for:
  16. -- SynthWorks Design Inc.
  17. -- VHDL Training Classes
  18. -- 11898 SW 128th Ave. Tigard, Or 97223
  19. -- http://www.SynthWorks.com
  20. --
  21. -- Revision History:
  22. -- Date Version Description
  23. -- 01/2015: 2015.05 Initial revision
  24. -- 01/2016: 2016.01 Update for L.all(L'left)
  25. -- 11/2016: 2016.11 Added IsUpper, IsLower, to_upper, to_lower
  26. --
  27. --
  28. -- Copyright (c) 2015-2016 by SynthWorks Design Inc. All rights reserved.
  29. --
  30. -- Verbatim copies of this source file may be used and
  31. -- distributed without restriction.
  32. --
  33. -- This source file is free software; you can redistribute it
  34. -- and/or modify it under the terms of the ARTISTIC License
  35. -- as published by The Perl Foundation; either version 2.0 of
  36. -- the License, or (at your option) any later version.
  37. --
  38. -- This source is distributed in the hope that it will be
  39. -- useful, but WITHOUT ANY WARRANTY; without even the implied
  40. -- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  41. -- PURPOSE. See the Artistic License for details.
  42. --
  43. -- You should have received a copy of the license with this source.
  44. -- If not download it from,
  45. -- http://www.perlfoundation.org/artistic_license_2_0
  46. --
  47. use std.textio.all ;
  48. library ieee ;
  49. use ieee.std_logic_1164.all ;
  50. package TextUtilPkg is
  51. ------------------------------------------------------------
  52. function IsUpper (constant Char : character ) return boolean ;
  53. function IsLower (constant Char : character ) return boolean ;
  54. function to_lower (constant Char : character ) return character ;
  55. function to_lower (constant Str : string ) return string ;
  56. function to_upper (constant Char : character ) return character ;
  57. function to_upper (constant Str : string ) return string ;
  58. function ishex (constant Char : character ) return boolean ;
  59. function isstd_logic (constant Char : character ) return boolean ;
  60. ------------------------------------------------------------
  61. procedure SkipWhiteSpace (
  62. ------------------------------------------------------------
  63. variable L : InOut line ;
  64. variable Empty : out boolean
  65. ) ;
  66. procedure SkipWhiteSpace (variable L : InOut line) ;
  67. ------------------------------------------------------------
  68. procedure EmptyOrCommentLine (
  69. ------------------------------------------------------------
  70. variable L : InOut line ;
  71. variable Empty : InOut boolean ;
  72. variable MultiLineComment : inout boolean
  73. ) ;
  74. ------------------------------------------------------------
  75. procedure ReadHexToken (
  76. -- Reads Upto Result'length values, less is ok.
  77. -- Does not skip white space
  78. ------------------------------------------------------------
  79. variable L : InOut line ;
  80. variable Result : Out std_logic_vector ;
  81. variable StrLen : Out integer
  82. ) ;
  83. ------------------------------------------------------------
  84. procedure ReadBinaryToken (
  85. -- Reads Upto Result'length values, less is ok.
  86. -- Does not skip white space
  87. ------------------------------------------------------------
  88. variable L : InOut line ;
  89. variable Result : Out std_logic_vector ;
  90. variable StrLen : Out integer
  91. ) ;
  92. end TextUtilPkg ;
  93. --- ///////////////////////////////////////////////////////////////////////////
  94. --- ///////////////////////////////////////////////////////////////////////////
  95. --- ///////////////////////////////////////////////////////////////////////////
  96. package body TextUtilPkg is
  97. constant LOWER_TO_UPPER_OFFSET : integer := character'POS('a') - character'POS('A') ;
  98. ------------------------------------------------------------
  99. function "-" (R : character ; L : integer ) return character is
  100. ------------------------------------------------------------
  101. begin
  102. return character'VAL(character'pos(R) - L) ;
  103. end function "-" ;
  104. ------------------------------------------------------------
  105. function "+" (R : character ; L : integer ) return character is
  106. ------------------------------------------------------------
  107. begin
  108. return character'VAL(character'pos(R) + L) ;
  109. end function "+" ;
  110. ------------------------------------------------------------
  111. function IsUpper (constant Char : character ) return boolean is
  112. ------------------------------------------------------------
  113. begin
  114. if Char >= 'A' and Char <= 'Z' then
  115. return TRUE ;
  116. else
  117. return FALSE ;
  118. end if ;
  119. end function IsUpper ;
  120. ------------------------------------------------------------
  121. function IsLower (constant Char : character ) return boolean is
  122. ------------------------------------------------------------
  123. begin
  124. if Char >= 'a' and Char <= 'z' then
  125. return TRUE ;
  126. else
  127. return FALSE ;
  128. end if ;
  129. end function IsLower ;
  130. ------------------------------------------------------------
  131. function to_lower (constant Char : character ) return character is
  132. ------------------------------------------------------------
  133. begin
  134. if IsUpper(Char) then
  135. return Char + LOWER_TO_UPPER_OFFSET ;
  136. else
  137. return Char ;
  138. end if ;
  139. end function to_lower ;
  140. ------------------------------------------------------------
  141. function to_lower (constant Str : string ) return string is
  142. ------------------------------------------------------------
  143. variable result : string(Str'range) ;
  144. begin
  145. for i in Str'range loop
  146. result(i) := to_lower(Str(i)) ;
  147. end loop ;
  148. return result ;
  149. end function to_lower ;
  150. ------------------------------------------------------------
  151. function to_upper (constant Char : character ) return character is
  152. ------------------------------------------------------------
  153. begin
  154. if IsLower(Char) then
  155. return Char - LOWER_TO_UPPER_OFFSET ;
  156. else
  157. return Char ;
  158. end if ;
  159. end function to_upper ;
  160. ------------------------------------------------------------
  161. function to_upper (constant Str : string ) return string is
  162. ------------------------------------------------------------
  163. variable result : string(Str'range) ;
  164. begin
  165. for i in Str'range loop
  166. result(i) := to_upper(Str(i)) ;
  167. end loop ;
  168. return result ;
  169. end function to_upper ;
  170. ------------------------------------------------------------
  171. function ishex (constant Char : character ) return boolean is
  172. ------------------------------------------------------------
  173. begin
  174. if Char >= '0' and Char <= '9' then
  175. return TRUE ;
  176. elsif Char >= 'a' and Char <= 'f' then
  177. return TRUE ;
  178. elsif Char >= 'A' and Char <= 'F' then
  179. return TRUE ;
  180. else
  181. return FALSE ;
  182. end if ;
  183. end function ishex ;
  184. ------------------------------------------------------------
  185. function isstd_logic (constant Char : character ) return boolean is
  186. ------------------------------------------------------------
  187. begin
  188. case Char is
  189. when 'U' | 'X' | '0' | '1' | 'Z' | 'W' | 'L' | 'H' | '-' =>
  190. return TRUE ;
  191. when others =>
  192. return FALSE ;
  193. end case ;
  194. end function isstd_logic ;
  195. -- ------------------------------------------------------------
  196. -- function iscomment (constant Char : character ) return boolean is
  197. -- ------------------------------------------------------------
  198. -- begin
  199. -- case Char is
  200. -- when '#' | '/' | '-' =>
  201. -- return TRUE ;
  202. -- when others =>
  203. -- return FALSE ;
  204. -- end case ;
  205. -- end function iscomment ;
  206. ------------------------------------------------------------
  207. procedure SkipWhiteSpace (
  208. ------------------------------------------------------------
  209. variable L : InOut line ;
  210. variable Empty : out boolean
  211. ) is
  212. variable Valid : boolean ;
  213. variable Char : character ;
  214. constant NBSP : CHARACTER := CHARACTER'val(160); -- space character
  215. begin
  216. Empty := TRUE ;
  217. WhiteSpLoop : while L /= null and L.all'length > 0 loop
  218. if (L.all(L'left) = ' ' or L.all(L'left) = NBSP or L.all(L'left) = HT) then
  219. read (L, Char, Valid) ;
  220. exit when not Valid ;
  221. else
  222. Empty := FALSE ;
  223. return ;
  224. end if ;
  225. end loop WhiteSpLoop ;
  226. end procedure SkipWhiteSpace ;
  227. ------------------------------------------------------------
  228. procedure SkipWhiteSpace (
  229. ------------------------------------------------------------
  230. variable L : InOut line
  231. ) is
  232. variable Empty : boolean ;
  233. begin
  234. SkipWhiteSpace(L, Empty) ;
  235. end procedure SkipWhiteSpace ;
  236. ------------------------------------------------------------
  237. -- Package Local
  238. procedure FindCommentEnd (
  239. ------------------------------------------------------------
  240. variable L : InOut line ;
  241. variable Empty : out boolean ;
  242. variable MultiLineComment : inout boolean
  243. ) is
  244. variable Valid : boolean ;
  245. variable Char : character ;
  246. begin
  247. MultiLineComment := TRUE ;
  248. Empty := TRUE ;
  249. FindEndOfCommentLoop : while L /= null and L.all'length > 1 loop
  250. read(L, Char, Valid) ;
  251. if Char = '*' and L.all(L'left) = '/' then
  252. read(L, Char, Valid) ;
  253. Empty := FALSE ;
  254. MultiLineComment := FALSE ;
  255. exit FindEndOfCommentLoop ;
  256. end if ;
  257. end loop ;
  258. end procedure FindCommentEnd ;
  259. ------------------------------------------------------------
  260. procedure EmptyOrCommentLine (
  261. ------------------------------------------------------------
  262. variable L : InOut line ;
  263. variable Empty : InOut boolean ;
  264. variable MultiLineComment : inout boolean
  265. ) is
  266. variable Valid : boolean ;
  267. variable Next2Char : string(1 to 2) ;
  268. constant NBSP : CHARACTER := CHARACTER'val(160); -- space character
  269. begin
  270. if MultiLineComment then
  271. FindCommentEnd(L, Empty, MultiLineComment) ;
  272. end if ;
  273. EmptyCheckLoop : while not MultiLineComment loop
  274. SkipWhiteSpace(L, Empty) ;
  275. exit when Empty ; -- line null or 0 in length detected by SkipWhite
  276. Empty := TRUE ;
  277. exit when L.all(L'left) = '#' ; -- shell style comment
  278. if L.all'length >= 2 then
  279. if L'ascending then
  280. Next2Char := L.all(L'left to L'left+1) ;
  281. else
  282. Next2Char := L.all(L'left to L'left-1) ;
  283. end if;
  284. exit when Next2Char = "//" ; -- C style comment
  285. exit when Next2Char = "--" ; -- VHDL style comment
  286. if Next2Char = "/*" then -- C style multi line comment
  287. FindCommentEnd(L, Empty, MultiLineComment) ;
  288. exit when Empty ;
  289. next EmptyCheckLoop ; -- Found end of comment, restart processing line
  290. end if ;
  291. end if ;
  292. Empty := FALSE ;
  293. exit ;
  294. end loop EmptyCheckLoop ;
  295. end procedure EmptyOrCommentLine ;
  296. ------------------------------------------------------------
  297. procedure ReadHexToken (
  298. -- Reads Upto Result'length values, less is ok.
  299. -- Does not skip white space
  300. ------------------------------------------------------------
  301. variable L : InOut line ;
  302. variable Result : Out std_logic_vector ;
  303. variable StrLen : Out integer
  304. ) is
  305. constant NumHexChars : integer := (Result'length+3)/4 ;
  306. constant ResultNormLen : integer := NumHexChars * 4 ;
  307. variable NextChar : character ;
  308. variable CharCount : integer ;
  309. variable ReturnVal : std_logic_vector(ResultNormLen-1 downto 0) ;
  310. variable ReadVal : std_logic_vector(3 downto 0) ;
  311. variable ReadValid : boolean ;
  312. begin
  313. ReturnVal := (others => '0') ;
  314. CharCount := 0 ;
  315. ReadLoop : while L /= null and L.all'length > 0 loop
  316. NextChar := L.all(L'left) ;
  317. if ishex(NextChar) or NextChar = 'X' or NextChar = 'Z' then
  318. hread(L, ReadVal, ReadValid) ;
  319. ReturnVal := ReturnVal(ResultNormLen-5 downto 0) & ReadVal ;
  320. CharCount := CharCount + 1 ;
  321. exit ReadLoop when CharCount >= NumHexChars ;
  322. elsif NextChar = '_' then
  323. read(L, NextChar, ReadValid) ;
  324. else
  325. exit ;
  326. end if ;
  327. end loop ReadLoop ;
  328. if CharCount >= NumHexChars then
  329. StrLen := Result'length ;
  330. else
  331. StrLen := CharCount * 4 ;
  332. end if ;
  333. Result := ReturnVal(Result'length-1 downto 0) ;
  334. end procedure ReadHexToken ;
  335. ------------------------------------------------------------
  336. procedure ReadBinaryToken (
  337. -- Reads Upto Result'length values, less is ok.
  338. -- Does not skip white space
  339. ------------------------------------------------------------
  340. variable L : InOut line ;
  341. variable Result : Out std_logic_vector ;
  342. variable StrLen : Out integer
  343. ) is
  344. variable NextChar : character ;
  345. variable CharCount : integer ;
  346. variable ReadVal : std_logic ;
  347. variable ReturnVal : std_logic_vector(Result'length-1 downto 0) ;
  348. variable ReadValid : boolean ;
  349. begin
  350. ReturnVal := (others => '0') ;
  351. CharCount := 0 ;
  352. ReadLoop : while L /= null and L.all'length > 0 loop
  353. NextChar := L.all(L'left) ;
  354. if isstd_logic(NextChar) then
  355. read(L, ReadVal, ReadValid) ;
  356. ReturnVal := ReturnVal(Result'length-2 downto 0) & ReadVal ;
  357. CharCount := CharCount + 1 ;
  358. exit ReadLoop when CharCount >= Result'length ;
  359. elsif NextChar = '_' then
  360. read(L, NextChar, ReadValid) ;
  361. else
  362. exit ;
  363. end if ;
  364. end loop ReadLoop ;
  365. StrLen := CharCount ;
  366. Result := ReturnVal ;
  367. end procedure ReadBinaryToken ;
  368. end package body TextUtilPkg ;